Merge branch 'terrastruct:master' into master

This commit is contained in:
Alexander Wang 2023-02-03 22:36:26 -08:00 committed by GitHub
commit 50e7d2f9ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
893 changed files with 64257 additions and 34356 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@
*.got.svg
e2e_report.html
bin
out

View file

@ -222,7 +222,7 @@ let us know and we'll be happy to include it here!
- **Python D2 diagram builder**: [https://github.com/MrBlenny/py-d2](https://github.com/MrBlenny/py-d2)
- **Clojure D2 transpiler**: [https://github.com/judepayne/dictim](https://github.com/judepayne/dictim)
- **JavaScript D2 diagram builder**: [https://github.com/Kreshnik/d2lang-js](https://github.com/Kreshnik/d2lang-js)
- **Maven plugin**: [https://github.com/andrinmeier/unofficial-d2lang-confluence-plugin](https://github.com/andrinmeier/unofficial-d2lang-confluence-plugin)
- **Maven plugin**: [https://github.com/andrinmeier/unofficial-d2lang-maven-plugin](https://github.com/andrinmeier/unofficial-d2lang-maven-plugin)
- **Confluence plugin**: [https://github.com/andrinmeier/unofficial-d2lang-confluence-plugin](https://github.com/andrinmeier/unofficial-d2lang-confluence-plugin)
- **CIL (C#, Visual Basic, F#, C++ CLR) to D2**: [https://github.com/HugoVG/AppDiagram](https://github.com/HugoVG/AppDiagram)

19
ci/cov.sh Executable file
View file

@ -0,0 +1,19 @@
#!/bin/sh
set -eu
cd -- "$(dirname "$0")/.."
. ./ci/sub/lib.sh
main() {
if [ "$*" = "" ]; then
set ./...
fi
mkdir -p out
capcode ./ci/test.sh -covermode=atomic -coverprofile=out/cov.prof "$@"
go tool cover -html=out/cov.prof -o=out/cov.html
go tool cover -func=out/cov.prof | grep '^total:' \
| sed 's#^total:.*(statements)[[:space:]]*\([0-9.%]*\)#TOTAL:\t\1#'
return "$code"
}
main "$@"

View file

@ -1,7 +1,7 @@
#!/bin/sh
set -eu
export REPORT_OUTPUT="out/e2e_report.html"
export REPORT_OUTPUT="./e2etests/out/e2e_report.html"
rm -f $REPORT_OUTPUT
export E2E_REPORT=1

View file

@ -7,7 +7,9 @@ RUN apt-get update && apt-get install -y ca-certificates curl dumb-init sudo
RUN curl -fsSL https://deb.nodesource.com/setup_19.x | bash -s - && \
apt-get install -y nodejs
RUN npx playwright install-deps
# https://github.com/microsoft/playwright/issues/18319
# Hopefully soon.
RUN if [ "$TARGETARCH" = amd64 ]; then npx playwright install-deps; fi
RUN adduser --gecos '' --disabled-password debian \
&& echo "debian ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
@ -26,7 +28,7 @@ RUN mkdir -p /usr/local/lib/d2 \
&& rm -Rf /tmp/d2-*-linux-"$TARGETARCH".tar.gz
USER debian:debian
RUN d2 init-playwright
RUN if [ "$TARGETARCH" = amd64 ]; then d2 init-playwright; fi
WORKDIR /home/debian/src
EXPOSE 8080

View file

@ -33,11 +33,11 @@ main() {
done
shift "$FLAGSHIFT"
REMOTE_HOST=$CI_HOST_D2_LINUX_AMD64 && runjob linux-amd64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_HOST_D2_LINUX_ARM64 && runjob linux-arm64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_HOST_D2_MACOS_AMD64 && runjob macos-amd64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_HOST_D2_MACOS_ARM64 && runjob macos-arm64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_HOST_D2_WINDOWS_AMD64 && runjob macos-arm64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_D2_LINUX_AMD64 && runjob linux-amd64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_D2_LINUX_ARM64 && runjob linux-arm64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_D2_MACOS_AMD64 && runjob macos-amd64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_D2_MACOS_ARM64 && runjob macos-arm64 ssh "$REMOTE_HOST" "$@"
REMOTE_HOST=$CI_D2_WINDOWS_AMD64 && runjob windows-amd64 ssh "$REMOTE_HOST" "$@"
}
main "$@"

View file

@ -2,14 +2,33 @@
- `double-border` keyword implemented. [#565](https://github.com/terrastruct/d2/pull/565)
- The [Dockerfile](./docs/INSTALL.md#docker) now supports rendering PNGs [#594](https://github.com/terrastruct/d2/issues/594)
- There was a minor breaking change as part of this where the default working directory of the Dockerfile is now `/home/debian/src` instead of `/root/src` to allow UID remapping with [`fixuid`](https://github.com/boxboat/fixuid).
- `d2 fmt` accepts multiple files to be formatted [#718](https://github.com/terrastruct/d2/issues/718)
- You can now use the reserved keywords `layers`/`scenarios`/`steps` to define diagrams
with multiple levels of abstractions. [#714](https://github.com/terrastruct/d2/pull/714)
Docs to come soon
- [#416](https://github.com/terrastruct/d2/issues/416) was also fixed so you can no
longer use keywords intended for use under `style` outside and vice versa. e.g.
`obj.style.shape` and `obj.double-border` are now illegal. The correct uses are
`obj.shape` and `obj.style.double-border`.
- Many other minor compiler bugs were fixed.
#### Improvements 🧹
- Code snippets use bold and italic font styles as determined by highlighter [#710](https://github.com/terrastruct/d2/issues/710), [#741](https://github.com/terrastruct/d2/issues/741)
- Reduces default padding of shapes. [#702](https://github.com/terrastruct/d2/pull/702)
- Ensures labels fit inside shapes with shape-specific inner bounding boxes. [#702](https://github.com/terrastruct/d2/pull/702)
- Improves package shape dimensions with short height. [#702](https://github.com/terrastruct/d2/pull/702)
- Keeps person shape from becoming too distorted. [#702](https://github.com/terrastruct/d2/pull/702)
- Ensures shapes with icons have enough padding for their labels. [#702](https://github.com/terrastruct/d2/pull/702)
#### Bugfixes ⛑️
- Fixes groups overlapping in sequence diagrams when they end in a self loop. [#728](https://github.com/terrastruct/d2/pull/728)
- Fixes dimensions of unlabeled squares or circles with only a set width or height. [#702](https://github.com/terrastruct/d2/pull/702)
- Fixes scaling of actor shapes in sequence diagrams. [#702](https://github.com/terrastruct/d2/pull/702)
- Images can now be set to sizes smaller than 128x128. [#702](https://github.com/terrastruct/d2/pull/702)
- Fixes class height when there are no rows. [#756](https://github.com/terrastruct/d2/pull/756)

2
ci/sub

@ -1 +1 @@
Subproject commit 8ac704818b5d7ab519e4b87caf5eb79716493709
Subproject commit 2009cdd523e00cc2e9b8ba804095f71ca70d5671

View file

@ -1,3 +1,5 @@
// TODO: Remove boxes and cleanup like d2ir
//
// d2ast implements the d2 language's abstract syntax tree.
//
// Special characters to think about in parser:
@ -149,6 +151,10 @@ func (r *Range) UnmarshalText(b []byte) (err error) {
return r.End.UnmarshalText(end)
}
func (r Range) Before(r2 Range) bool {
return r.Start.Before(r2.Start)
}
// Position represents a line:column and byte position in a file.
//
// note: Line and Column are zero indexed.
@ -257,6 +263,10 @@ func (p Position) SubtractString(s string, byUTF16 bool) Position {
return p
}
func (p Position) Before(p2 Position) bool {
return p.Byte < p2.Byte
}
// MapNode is implemented by nodes that may be children of Maps.
type MapNode interface {
Node
@ -402,7 +412,7 @@ func (s *SingleQuotedString) scalar() {}
func (s *BlockString) scalar() {}
// TODO: mistake, move into parse.go
func (n *Null) ScalarString() string { return n.Type() }
func (n *Null) ScalarString() string { return "" }
func (b *Boolean) ScalarString() string { return strconv.FormatBool(b.Value) }
func (n *Number) ScalarString() string { return n.Raw }
func (s *UnquotedString) ScalarString() string {
@ -648,6 +658,21 @@ type KeyPath struct {
Path []*StringBox `json:"path"`
}
func MakeKeyPath(a []string) *KeyPath {
kp := &KeyPath{}
for _, el := range a {
kp.Path = append(kp.Path, MakeValueBox(RawString(el, true)).StringBox())
}
return kp
}
func (kp *KeyPath) IDA() (ida []string) {
for _, el := range kp.Path {
ida = append(ida, el.Unbox().ScalarString())
}
return ida
}
type Edge struct {
Range Range `json:"range"`
@ -729,6 +754,37 @@ type ArrayNodeBox struct {
Map *Map `json:"map,omitempty"`
}
func MakeArrayNodeBox(an ArrayNode) ArrayNodeBox {
var ab ArrayNodeBox
switch an := an.(type) {
case *Comment:
ab.Comment = an
case *BlockComment:
ab.BlockComment = an
case *Substitution:
ab.Substitution = an
case *Null:
ab.Null = an
case *Boolean:
ab.Boolean = an
case *Number:
ab.Number = an
case *UnquotedString:
ab.UnquotedString = an
case *DoubleQuotedString:
ab.DoubleQuotedString = an
case *SingleQuotedString:
ab.SingleQuotedString = an
case *BlockString:
ab.BlockString = an
case *Array:
ab.Array = an
case *Map:
ab.Map = an
}
return ab
}
func (ab ArrayNodeBox) Unbox() ArrayNode {
switch {
case ab.Comment != nil:

View file

@ -18,10 +18,11 @@ import (
func GenDSL(maxi int) (_ string, err error) {
gs := &dslGenState{
rand: mathrand.New(mathrand.NewSource(time.Now().UnixNano())),
g: d2graph.NewGraph(&d2ast.Map{}),
g: d2graph.NewGraph(),
nodeShapes: make(map[string]string),
nodeContainer: make(map[string]string),
}
gs.g.AST = &d2ast.Map{}
err = gs.gen(maxi)
if err != nil {
return "", err

File diff suppressed because it is too large Load diff

View file

@ -8,12 +8,13 @@ import (
tassert "github.com/stretchr/testify/assert"
"oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/util-go/diff"
"oss.terrastruct.com/d2/d2compiler"
"oss.terrastruct.com/d2/d2format"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/util-go/diff"
)
func TestCompile(t *testing.T) {
@ -123,8 +124,7 @@ x: {
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/equal_dimensions_on_circle.d2:3:2: width and height must be equal for circle shapes
d2/testdata/d2compiler/TestCompile/equal_dimensions_on_circle.d2:4:2: width and height must be equal for circle shapes
`,
d2/testdata/d2compiler/TestCompile/equal_dimensions_on_circle.d2:4:2: width and height must be equal for circle shapes`,
},
{
name: "single_dimension_on_circle",
@ -207,8 +207,7 @@ d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:16:3: height c
d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:25:3: width cannot be used on container: containers.oval container
d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:26:3: height cannot be used on container: containers.oval container
d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:36:3: width cannot be used on container: containers.hexagon container
d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:37:3: height cannot be used on container: containers.hexagon container
`,
d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:37:3: height cannot be used on container: containers.hexagon container`,
},
{
name: "dimension_with_style",
@ -241,8 +240,7 @@ d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:37:3: height c
}
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/shape_unquoted_hex.d2:3:10: missing value after colon
`,
expErr: `d2/testdata/d2compiler/TestCompile/shape_unquoted_hex.d2:3:10: missing value after colon`,
},
{
name: "edge_unquoted_hex",
@ -253,8 +251,7 @@ d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:37:3: height c
}
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/edge_unquoted_hex.d2:3:10: missing value after colon
`,
expErr: `d2/testdata/d2compiler/TestCompile/edge_unquoted_hex.d2:3:10: missing value after colon`,
},
{
name: "blank_underscore",
@ -264,8 +261,7 @@ d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:37:3: height c
_
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/blank_underscore.d2:3:3: invalid use of parent "_"
`,
expErr: `d2/testdata/d2compiler/TestCompile/blank_underscore.d2:3:3: field key must contain more than underscores`,
},
{
name: "image_non_style",
@ -276,8 +272,7 @@ d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:37:3: height c
name: y
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/image_non_style.d2:4:3: image shapes cannot have children.
`,
expErr: `d2/testdata/d2compiler/TestCompile/image_non_style.d2:4:3: image shapes cannot have children.`,
},
{
name: "stroke-width",
@ -302,8 +297,7 @@ d2/testdata/d2compiler/TestCompile/no_dimensions_on_containers.d2:37:3: height c
style.stroke-width: -1
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/illegal-stroke-width.d2:2:23: expected "stroke-width" to be a number between 0 and 15
`,
expErr: `d2/testdata/d2compiler/TestCompile/illegal-stroke-width.d2:2:23: expected "stroke-width" to be a number between 0 and 15`,
},
{
name: "underscore_parent_create",
@ -340,8 +334,7 @@ x: {
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, "y", g.Objects[1].ID)
tassert.Equal(t, g.Root.AbsID(), g.Objects[1].References[0].ScopeObj.AbsID())
tassert.Equal(t, g.Objects[0].AbsID(), g.Objects[1].References[0].UnresolvedScopeObj.AbsID())
tassert.Equal(t, g.Objects[0].AbsID(), g.Objects[1].References[0].ScopeObj.AbsID())
},
},
{
@ -456,8 +449,7 @@ x: {
text: `
_.x
`,
expErr: `d2/testdata/d2compiler/TestCompile/underscore_parent_root.d2:2:1: parent "_" cannot be used in the root scope
`,
expErr: `d2/testdata/d2compiler/TestCompile/underscore_parent_root.d2:2:1: invalid underscore: no parent`,
},
{
name: "underscore_parent_middle_path",
@ -467,8 +459,7 @@ x: {
y._.z
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/underscore_parent_middle_path.d2:3:3: parent "_" can only be used in the beginning of paths, e.g. "_.x"
`,
expErr: `d2/testdata/d2compiler/TestCompile/underscore_parent_middle_path.d2:3:5: parent "_" can only be used in the beginning of paths, e.g. "_.x"`,
},
{
name: "underscore_parent_sandwich_path",
@ -478,8 +469,7 @@ x: {
_.z._
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/underscore_parent_sandwich_path.d2:3:3: parent "_" can only be used in the beginning of paths, e.g. "_.x"
`,
expErr: `d2/testdata/d2compiler/TestCompile/underscore_parent_sandwich_path.d2:3:7: parent "_" can only be used in the beginning of paths, e.g. "_.x"`,
},
{
name: "underscore_edge",
@ -996,8 +986,7 @@ x -> y: {
text: `x: {shape: triangle}
`,
expErr: `d2/testdata/d2compiler/TestCompile/object_arrowhead_shape.d2:1:5: invalid shape, can only set "triangle" for arrowheads
`,
expErr: `d2/testdata/d2compiler/TestCompile/object_arrowhead_shape.d2:1:5: invalid shape, can only set "triangle" for arrowheads`,
},
{
name: "edge_flat_label_arrowhead",
@ -1083,8 +1072,7 @@ x -> y: {
space -> stars
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/nested_edge.d2:1:1: edges cannot be nested within another edge
`,
expErr: `d2/testdata/d2compiler/TestCompile/nested_edge.d2:2:3: cannot create edge inside edge`,
},
{
name: "shape_edge_style",
@ -1094,8 +1082,7 @@ x: {
style.animated: true
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/shape_edge_style.d2:3:2: key "animated" can only be applied to edges
`,
expErr: `d2/testdata/d2compiler/TestCompile/shape_edge_style.d2:3:2: key "animated" can only be applied to edges`,
},
{
name: "edge_chain_map",
@ -1351,8 +1338,7 @@ x -> y: {
z
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/edge_map_non_reserved.d2:2:1: edge map keys must be reserved keywords
`,
expErr: `d2/testdata/d2compiler/TestCompile/edge_map_non_reserved.d2:3:3: edge map keys must be reserved keywords`,
},
{
name: "url_link",
@ -1397,8 +1383,7 @@ x -> y: {
text: `x.near: txop-center
`,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_constant.d2:1:1: 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",
@ -1408,8 +1393,7 @@ x -> y: {
y
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_container.d2:1:1: constant near keys cannot be set on shapes with children
`,
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",
@ -1419,16 +1403,14 @@ x -> y: {
}
x -> y
`,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_connected.d2:1:1: constant near keys cannot be set on connected shapes
`,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_connected.d2:2:9: constant near keys cannot be set on connected shapes`,
},
{
name: "nested_near_constant",
text: `x.y.near: top-center
`,
expErr: `d2/testdata/d2compiler/TestCompile/nested_near_constant.d2:1:1: constant near keys can only be set on root level shapes
`,
expErr: `d2/testdata/d2compiler/TestCompile/nested_near_constant.d2:1:11: constant near keys can only be set on root level shapes`,
},
{
name: "reserved_icon_near_style",
@ -1474,17 +1456,14 @@ y
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/errors/reserved_icon_style.d2:3:9: bad icon url "::????:::%%orange": parse "::????:::%%orange": missing protocol scheme
d2/testdata/d2compiler/TestCompile/errors/reserved_icon_style.d2:4:18: expected "opacity" to be a number between 0.0 and 1.0
d2/testdata/d2compiler/TestCompile/errors/reserved_icon_style.d2:5:18: expected "opacity" to be a number between 0.0 and 1.0
d2/testdata/d2compiler/TestCompile/errors/reserved_icon_style.d2:1:1: near key "y" 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
`,
d2/testdata/d2compiler/TestCompile/errors/reserved_icon_style.d2:2:9: near key "y" 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: "errors/missing_shape_icon",
text: `x.shape: image`,
expErr: `d2/testdata/d2compiler/TestCompile/errors/missing_shape_icon.d2:1:1: image shape must include an "icon" field
`,
text: `x.shape: image`,
expErr: `d2/testdata/d2compiler/TestCompile/errors/missing_shape_icon.d2:1:1: image shape must include an "icon" field`,
},
{
name: "edge_in_column",
@ -1500,8 +1479,7 @@ d2/testdata/d2compiler/TestCompile/errors/reserved_icon_style.d2:1:1: near key "
text: `x: {style.opacity: 0.4}
y -> x.style
`,
expErr: `d2/testdata/d2compiler/TestCompile/edge_to_style.d2:2:1: cannot connect to reserved keyword
`,
expErr: `d2/testdata/d2compiler/TestCompile/edge_to_style.d2:2:8: reserved keywords are prohibited in edges`,
},
{
name: "escaped_id",
@ -1581,7 +1559,7 @@ b`, g.Objects[0].Attributes.Label.Value)
GetType(): string
style: {
opacity: 0.4
color: blue
font-color: blue
}
}
`,
@ -1680,10 +1658,9 @@ x.y -> a.b: {
{
name: "3d_oval",
text: `SVP1.style.shape: oval
text: `SVP1.shape: oval
SVP1.style.3d: true`,
expErr: `d2/testdata/d2compiler/TestCompile/3d_oval.d2:2:1: key "3d" can only be applied to squares and rectangles
`,
expErr: `d2/testdata/d2compiler/TestCompile/3d_oval.d2:2:1: key "3d" can only be applied to squares and rectangles`,
}, {
name: "edge_column_index",
text: `src: {
@ -1740,8 +1717,7 @@ dst.id <-> src.dst_id
}
b -> x.a
`,
expErr: `d2/testdata/d2compiler/TestCompile/leaky_sequence.d2:5:1: connections within sequence diagrams can connect only to other objects within the same sequence diagram
`,
expErr: `d2/testdata/d2compiler/TestCompile/leaky_sequence.d2:5:1: connections within sequence diagrams can connect only to other objects within the same sequence diagram`,
},
{
name: "sequence_scoping",
@ -1775,6 +1751,35 @@ choo: {
tassert.Equal(t, 3, len(g.Root.ChildrenArray))
},
},
{
name: "sequence_container",
text: `shape: sequence_diagram
x.y.q -> j.y.p
ok: {
x.y.q -> j.y.p
}
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, 7, len(g.Objects))
tassert.Equal(t, 3, len(g.Root.ChildrenArray))
},
},
{
name: "sequence_container_2",
text: `shape: sequence_diagram
x.y.q
ok: {
x.y.q -> j.y.p
meow
}
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, 8, len(g.Objects))
tassert.Equal(t, 2, len(g.Root.ChildrenArray))
},
},
{
name: "root_direction",
@ -1818,8 +1823,7 @@ choo: {
text: `x: {
direction: diagonal
}`,
expErr: `d2/testdata/d2compiler/TestCompile/invalid_direction.d2:2:14: direction must be one of up, down, right, left, got "diagonal"
`,
expErr: `d2/testdata/d2compiler/TestCompile/invalid_direction.d2:2:14: direction must be one of up, down, right, left, got "diagonal"`,
},
{
name: "self-referencing",
@ -1868,8 +1872,7 @@ choo: {
test_id: varchar(64) {constraint: [primary_key, foreign_key]}
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/sql-panic.d2:3:27: constraint value must be a string
`,
expErr: `d2/testdata/d2compiler/TestCompile/sql-panic.d2:3:27: reserved field constraint does not accept composite`,
},
{
name: "wrong_column_index",
@ -1939,3 +1942,167 @@ Chinchillas_Collectibles.chinchilla -> Chinchillas.id`,
})
}
}
func TestCompile2(t *testing.T) {
t.Parallel()
t.Run("boards", testBoards)
t.Run("seqdiagrams", testSeqDiagrams)
}
func testBoards(t *testing.T) {
t.Parallel()
tca := []struct {
name string
run func(t *testing.T)
}{
{
name: "root",
run: func(t *testing.T) {
g := assertCompile(t, `base
layers: {
one: {
santa
}
two: {
clause
}
}
`, "")
assert.JSON(t, 2, len(g.Layers))
assert.JSON(t, "one", g.Layers[0].Name)
assert.JSON(t, "two", g.Layers[1].Name)
},
},
{
name: "recursive",
run: func(t *testing.T) {
g := assertCompile(t, `base
layers: {
one: {
santa
}
two: {
clause
steps: {
seinfeld: {
reindeer
}
missoula: {
montana
}
}
}
}
`, "")
assert.Equal(t, 2, len(g.Layers))
assert.Equal(t, "one", g.Layers[0].Name)
assert.Equal(t, "two", g.Layers[1].Name)
assert.Equal(t, 2, len(g.Layers[1].Steps))
},
},
{
name: "errs/duplicate_board",
run: func(t *testing.T) {
assertCompile(t, `base
layers: {
one: {
santa
}
}
steps: {
one: {
clause
}
}
`, `d2/testdata/d2compiler/TestCompile2/boards/errs/duplicate_board.d2:9:2: board name one already used by another board`)
},
},
}
for _, tc := range tca {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
tc.run(t)
})
}
}
func testSeqDiagrams(t *testing.T) {
t.Parallel()
t.Run("errs", func(t *testing.T) {
t.Parallel()
tca := []struct {
name string
skip bool
run func(t *testing.T)
}{
{
name: "sequence_diagram_edge_between_edge_groups",
// New sequence diagram scoping implementation is disabled.
skip: true,
run: func(t *testing.T) {
assertCompile(t, `
Office chatter: {
shape: sequence_diagram
alice: Alice
bob: Bobby
awkward small talk: {
alice -> bob: uhm, hi
bob -> alice: oh, hello
icebreaker attempt: {
alice -> bob: what did you have for lunch?
}
unfortunate outcome: {
bob -> alice: that's personal
}
}
awkward small talk.icebreaker attempt.alice -> awkward small talk.unfortunate outcome.bob
}
`, "d2/testdata/d2compiler/TestCompile2/seqdiagrams/errs/sequence_diagram_edge_between_edge_groups.d2:16:3: edges between edge groups are not allowed")
},
},
}
for _, tc := range tca {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if tc.skip {
t.SkipNow()
}
tc.run(t)
})
}
})
}
func assertCompile(t *testing.T, text string, expErr string) *d2graph.Graph {
d2Path := fmt.Sprintf("d2/testdata/d2compiler/%v.d2", t.Name())
g, err := d2compiler.Compile(d2Path, strings.NewReader(text), nil)
if expErr != "" {
assert.Error(t, err)
assert.ErrorString(t, err, expErr)
} else {
assert.Success(t, err)
}
got := struct {
Graph *d2graph.Graph `json:"graph"`
Err error `json:"err"`
}{
Graph: g,
Err: err,
}
err = diff.TestdataJSON(filepath.Join("..", "testdata", "d2compiler", t.Name()), got)
assert.Success(t, err)
return g
}

View file

@ -4,18 +4,20 @@ import (
"context"
"strconv"
"oss.terrastruct.com/util-go/go2"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2renderers/d2fonts"
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/d2themes"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
"oss.terrastruct.com/util-go/go2"
)
func Export(ctx context.Context, g *d2graph.Graph, themeID int64, fontFamily *d2fonts.FontFamily) (*d2target.Diagram, error) {
theme := d2themescatalog.Find(themeID)
diagram := d2target.NewDiagram()
diagram.Name = g.Name
if fontFamily == nil {
fontFamily = go2.Pointer(d2fonts.SourceSansPro)
}
@ -141,6 +143,7 @@ func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape {
}
shape.Label = text.Text
shape.LabelWidth = text.Dimensions.Width
shape.LabelHeight = text.Dimensions.Height
if obj.LabelPosition != nil {
shape.LabelPosition = *obj.LabelPosition

View file

@ -397,3 +397,15 @@ func (p *printer) edgeIndex(ei *d2ast.EdgeIndex) {
}
p.sb.WriteByte(']')
}
func KeyPath(kp *d2ast.KeyPath) (ida []string) {
for _, s := range kp.Path {
// We format each string of the key to ensure the resulting strings can be parsed
// correctly.
n := &d2ast.KeyPath{
Path: []*d2ast.StringBox{d2ast.MakeValueBox(d2ast.RawString(s.Unbox().ScalarString(), true)).StringBox()},
}
ida = append(ida, Format(n))
}
return ida
}

View file

@ -5,6 +5,7 @@ import (
"fmt"
"math"
"net/url"
"sort"
"strconv"
"strings"
@ -18,31 +19,34 @@ import (
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/d2themes"
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/shape"
"oss.terrastruct.com/d2/lib/textmeasure"
)
const INNER_LABEL_PADDING int = 5
const DEFAULT_SHAPE_PADDING = 100.
const DEFAULT_SHAPE_SIZE = 100.
const MIN_SHAPE_SIZE = 5
// TODO: Refactor with a light abstract layer on top of AST implementing scenarios,
// variables, imports, substitutions and then a final set of structures representing
// a final graph.
type Graph struct {
AST *d2ast.Map `json:"ast"`
Name string `json:"name"`
AST *d2ast.Map `json:"ast"`
Root *Object `json:"root"`
Edges []*Edge `json:"edges"`
Objects []*Object `json:"objects"`
Layers []*Graph `json:"layers,omitempty"`
Scenarios []*Graph `json:"scenarios,omitempty"`
Steps []*Graph `json:"steps,omitempty"`
}
func NewGraph(ast *d2ast.Map) *Graph {
d := &Graph{
AST: ast,
}
func NewGraph() *Graph {
d := &Graph{}
d.Root = &Object{
Graph: d,
Parent: nil,
Children: make(map[string]*Object),
Graph: d,
Parent: nil,
Children: make(map[string]*Object),
Attributes: &Attributes{},
}
return d
}
@ -82,7 +86,7 @@ type Object struct {
Children map[string]*Object `json:"-"`
ChildrenArray []*Object `json:"-"`
Attributes Attributes `json:"attributes"`
Attributes *Attributes `json:"attributes,omitempty"`
ZIndex int `json:"zIndex"`
}
@ -105,7 +109,8 @@ type Attributes struct {
// TODO: default to ShapeRectangle instead of empty string
Shape Scalar `json:"shape"`
Direction Scalar `json:"direction"`
Direction Scalar `json:"direction"`
Constraint Scalar `json:"constraint"`
}
// TODO references at the root scope should have their Scope set to root graph AST
@ -116,9 +121,7 @@ type Reference struct {
MapKey *d2ast.Key `json:"-"`
MapKeyEdgeIndex int `json:"map_key_edge_index"`
Scope *d2ast.Map `json:"-"`
// The ScopeObj and UnresolvedScopeObj are the same except when the key contains underscores
ScopeObj *Object `json:"-"`
UnresolvedScopeObj *Object `json:"-"`
ScopeObj *Object `json:"-"`
}
func (r Reference) MapKeyEdgeDest() bool {
@ -500,10 +503,13 @@ func (obj *Object) newObject(id string) *Object {
child := &Object{
ID: id,
IDVal: idval,
Attributes: Attributes{
Attributes: &Attributes{
Label: Scalar{
Value: idval,
},
Shape: Scalar{
Value: d2target.ShapeRectangle,
},
},
Graph: obj.Graph,
@ -523,6 +529,9 @@ func (obj *Object) newObject(id string) *Object {
}
func (obj *Object) HasChild(ids []string) (*Object, bool) {
if len(ids) == 0 {
return obj, true
}
if len(ids) == 1 && ids[0] != "style" {
_, ok := ReservedKeywords[ids[0]]
if ok {
@ -557,6 +566,7 @@ func (obj *Object) HasEdge(mk *d2ast.Key) (*Edge, bool) {
return nil, false
}
// TODO: remove once not used anywhere
func ResolveUnderscoreKey(ida []string, obj *Object) (resolvedObj *Object, resolvedIDA []string, _ error) {
if len(ida) > 0 && !obj.IsSequenceDiagram() {
objSD := obj.OuterSequenceDiagram()
@ -637,34 +647,71 @@ func (obj *Object) FindEdges(mk *d2ast.Key) ([]*Edge, bool) {
return ea, true
}
func (obj *Object) ensureChildEdge(ida []string) *Object {
for i := range ida {
switch obj.Attributes.Shape.Value {
case d2target.ShapeClass, d2target.ShapeSQLTable:
// This will only be called for connecting edges where we want to truncate to the
// container.
return obj
default:
obj = obj.EnsureChild(ida[i : i+1])
}
}
return obj
}
// EnsureChild grabs the child by ids or creates it if it does not exist including all
// intermediate nodes.
func (obj *Object) EnsureChild(ids []string) *Object {
_, is := ReservedKeywordHolders[ids[0]]
if len(ids) == 1 && !is {
_, ok := ReservedKeywords[ids[0]]
func (obj *Object) EnsureChild(ida []string) *Object {
seq := obj.OuterSequenceDiagram()
if seq != nil {
for _, c := range seq.ChildrenArray {
if c.ID == ida[0] {
if obj.ID == ida[0] {
// In cases of a.a where EnsureChild is called on the parent a, the second a should
// be created as a child of a and not as a child of the diagram. This is super
// unfortunate code but alas.
break
}
obj = seq
break
}
}
}
if len(ida) == 0 {
return obj
}
_, is := ReservedKeywordHolders[ida[0]]
if len(ida) == 1 && !is {
_, ok := ReservedKeywords[ida[0]]
if ok {
return obj
}
}
id := ids[0]
ids = ids[1:]
id := ida[0]
ida = ida[1:]
if id == "_" {
return obj.Parent.EnsureChild(ida)
}
child, ok := obj.Children[strings.ToLower(id)]
if !ok {
child = obj.newObject(id)
}
if len(ids) >= 1 {
return child.EnsureChild(ids)
if len(ida) >= 1 {
return child.EnsureChild(ida)
}
return child
}
func (obj *Object) AppendReferences(ida []string, ref Reference, unresolvedObj *Object) {
ref.ScopeObj = obj
ref.UnresolvedScopeObj = unresolvedObj
ref.ScopeObj = unresolvedObj
numUnderscores := 0
for i := range ida {
if ida[i] == "_" {
@ -730,9 +777,14 @@ func (obj *Object) GetLabelSize(mtexts []*d2target.MText, ruler *textmeasure.Rul
return dims, nil
}
func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, labelDims d2target.TextDimensions) (*d2target.TextDimensions, error) {
func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, labelDims d2target.TextDimensions, withLabelPadding bool) (*d2target.TextDimensions, error) {
dims := d2target.TextDimensions{}
if withLabelPadding {
labelDims.Width += INNER_LABEL_PADDING
labelDims.Height += INNER_LABEL_PADDING
}
switch strings.ToLower(obj.Attributes.Shape.Value) {
default:
return d2target.NewTextDimensions(labelDims.Width, labelDims.Height), nil
@ -748,22 +800,22 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
if fdims == nil {
return nil, fmt.Errorf("dimensions for class field %#v not found", f.Text())
}
lineWidth := fdims.Width
if maxWidth < lineWidth {
maxWidth = lineWidth
}
maxWidth = go2.Max(maxWidth, fdims.Width)
}
for _, m := range obj.Class.Methods {
mdims := GetTextDimensions(mtexts, ruler, m.Text(), go2.Pointer(d2fonts.SourceCodePro))
if mdims == nil {
return nil, fmt.Errorf("dimensions for class method %#v not found", m.Text())
}
lineWidth := mdims.Width
if maxWidth < lineWidth {
maxWidth = lineWidth
}
maxWidth = go2.Max(maxWidth, mdims.Width)
}
dims.Width = maxWidth
// ┌─PrefixWidth ┌─CenterPadding
// ┌─┬─┬───────┬──────┬───┬──┐
// │ + getJobs() Job[] │
// └─┴─┴───────┴──────┴───┴──┘
// └─PrefixPadding └──TypePadding
// ├───────┤ + ├───┤ = maxWidth
dims.Width = d2target.PrefixPadding + d2target.PrefixWidth + maxWidth + d2target.CenterPadding + d2target.TypePadding
// All rows should be the same height
var anyRowText *d2target.MText
@ -773,11 +825,10 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
anyRowText = obj.Class.Methods[0].Text()
}
if anyRowText != nil {
// 10px of padding top and bottom so text doesn't look squished
rowHeight := GetTextDimensions(mtexts, ruler, anyRowText, go2.Pointer(d2fonts.SourceCodePro)).Height + 20
rowHeight := GetTextDimensions(mtexts, ruler, anyRowText, go2.Pointer(d2fonts.SourceCodePro)).Height + d2target.VerticalPadding
dims.Height = rowHeight * (len(obj.Class.Fields) + len(obj.Class.Methods) + 2)
} else {
dims.Height = go2.Max(12, labelDims.Height)
dims.Height = 2*go2.Max(12, labelDims.Height) + d2target.VerticalPadding
}
case d2target.ShapeSQLTable:
@ -796,9 +847,7 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
}
c.Name.LabelWidth = nameDims.Width
c.Name.LabelHeight = nameDims.Height
if maxNameWidth < nameDims.Width {
maxNameWidth = nameDims.Width
}
maxNameWidth = go2.Max(maxNameWidth, nameDims.Width)
typeDims := GetTextDimensions(mtexts, ruler, ctexts[1], fontFamily)
if typeDims == nil {
@ -809,6 +858,7 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
if maxTypeWidth < typeDims.Width {
maxTypeWidth = typeDims.Width
}
maxTypeWidth = go2.Max(maxTypeWidth, typeDims.Width)
if c.Constraint != "" {
// covers UNQ constraint with padding
@ -826,21 +876,6 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
return &dims, nil
}
func (obj *Object) GetPadding() (x, y float64) {
switch strings.ToLower(obj.Attributes.Shape.Value) {
case d2target.ShapeImage,
d2target.ShapeSQLTable,
d2target.ShapeText,
d2target.ShapeCode:
return 0., 0.
case d2target.ShapeClass:
// TODO fix class row width measurements (see SQL table)
return 100., 0.
default:
return DEFAULT_SHAPE_PADDING, DEFAULT_SHAPE_PADDING
}
}
type Edge struct {
Index int `json:"index"`
@ -866,7 +901,7 @@ type Edge struct {
DstArrowhead *Attributes `json:"dstArrowhead,omitempty"`
References []EdgeReference `json:"references,omitempty"`
Attributes Attributes `json:"attributes"`
Attributes *Attributes `json:"attributes,omitempty"`
ZIndex int `json:"zIndex"`
}
@ -938,15 +973,6 @@ func (e *Edge) AbsID() string {
}
func (obj *Object) Connect(srcID, dstID []string, srcArrow, dstArrow bool, label string) (*Edge, error) {
srcObj, srcID, err := ResolveUnderscoreKey(srcID, obj)
if err != nil {
return nil, err
}
dstObj, dstID, err := ResolveUnderscoreKey(dstID, obj)
if err != nil {
return nil, err
}
for _, id := range [][]string{srcID, dstID} {
for _, p := range id {
if _, ok := ReservedKeywords[p]; ok {
@ -955,15 +981,15 @@ func (obj *Object) Connect(srcID, dstID []string, srcArrow, dstArrow bool, label
}
}
src := srcObj.EnsureChild(srcID)
dst := dstObj.EnsureChild(dstID)
src := obj.ensureChildEdge(srcID)
dst := obj.ensureChildEdge(dstID)
if src.OuterSequenceDiagram() != dst.OuterSequenceDiagram() {
return nil, errors.New("connections within sequence diagrams can connect only to other objects within the same sequence diagram")
}
edge := &Edge{
Attributes: Attributes{
e := &Edge{
Attributes: &Attributes{
Label: Scalar{
Value: label,
},
@ -973,10 +999,47 @@ func (obj *Object) Connect(srcID, dstID []string, srcArrow, dstArrow bool, label
Dst: dst,
DstArrow: dstArrow,
}
edge.initIndex()
e.initIndex()
obj.Graph.Edges = append(obj.Graph.Edges, edge)
return edge, nil
addSQLTableColumnIndices(e, srcID, dstID, obj, src, dst)
obj.Graph.Edges = append(obj.Graph.Edges, e)
return e, nil
}
func addSQLTableColumnIndices(e *Edge, srcID, dstID []string, obj, src, dst *Object) {
if src.Attributes.Shape.Value == d2target.ShapeSQLTable {
if src == dst {
// Ignore edge to column inside table.
return
}
objAbsID := obj.AbsIDArray()
srcAbsID := src.AbsIDArray()
if len(objAbsID)+len(srcID) > len(srcAbsID) {
for i, d2col := range src.SQLTable.Columns {
if d2col.Name.Label == srcID[len(srcID)-1] {
d2col.Reference = dst.AbsID()
e.SrcTableColumnIndex = new(int)
*e.SrcTableColumnIndex = i
break
}
}
}
}
if dst.Attributes.Shape.Value == d2target.ShapeSQLTable {
objAbsID := obj.AbsIDArray()
dstAbsID := dst.AbsIDArray()
if len(objAbsID)+len(dstID) > len(dstAbsID) {
for i, d2col := range dst.SQLTable.Columns {
if d2col.Name.Label == dstID[len(dstID)-1] {
d2col.Reference = dst.AbsID()
e.DstTableColumnIndex = new(int)
*e.DstTableColumnIndex = i
break
}
}
}
}
}
// TODO: Treat undirectional/bidirectional edge here and in HasEdge flipped. Same with
@ -1108,29 +1171,41 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
desiredHeight, _ = strconv.Atoi(obj.Attributes.Height.Value)
}
dslShape := strings.ToLower(obj.Attributes.Shape.Value)
if obj.Attributes.Label.Value == "" &&
obj.Attributes.Shape.Value != d2target.ShapeImage &&
obj.Attributes.Shape.Value != d2target.ShapeSQLTable &&
obj.Attributes.Shape.Value != d2target.ShapeClass {
obj.Width = DEFAULT_SHAPE_PADDING
obj.Height = DEFAULT_SHAPE_PADDING
if desiredWidth != 0 {
obj.Width = float64(desiredWidth)
}
if desiredHeight != 0 {
obj.Height = float64(desiredHeight)
dslShape != d2target.ShapeImage &&
dslShape != d2target.ShapeSQLTable &&
dslShape != d2target.ShapeClass {
if dslShape == d2target.ShapeCircle || dslShape == d2target.ShapeSquare {
sideLength := DEFAULT_SHAPE_SIZE
if desiredWidth != 0 || desiredHeight != 0 {
sideLength = float64(go2.Max(desiredWidth, desiredHeight))
}
obj.Width = sideLength
obj.Height = sideLength
} else {
obj.Width = DEFAULT_SHAPE_SIZE
obj.Height = DEFAULT_SHAPE_SIZE
if desiredWidth != 0 {
obj.Width = float64(desiredWidth)
}
if desiredHeight != 0 {
obj.Height = float64(desiredHeight)
}
}
continue
}
shapeType := strings.ToLower(obj.Attributes.Shape.Value)
labelDims, err := obj.GetLabelSize(mtexts, ruler, fontFamily)
if err != nil {
return err
}
obj.LabelDimensions = *labelDims
switch shapeType {
switch dslShape {
case d2target.ShapeText, d2target.ShapeClass, d2target.ShapeSQLTable, d2target.ShapeCode:
// no labels
default:
@ -1140,39 +1215,65 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
}
}
if shapeType != d2target.ShapeText && obj.Attributes.Label.Value != "" {
labelDims.Width += INNER_LABEL_PADDING
labelDims.Height += INNER_LABEL_PADDING
}
obj.LabelDimensions = *labelDims
defaultDims, err := obj.GetDefaultSize(mtexts, ruler, fontFamily, *labelDims)
// if there is a desired width or height, fit to content box without inner label padding for smallest minimum size
withInnerLabelPadding := desiredWidth == 0 && desiredHeight == 0 &&
dslShape != d2target.ShapeText && obj.Attributes.Label.Value != ""
defaultDims, err := obj.GetDefaultSize(mtexts, ruler, fontFamily, *labelDims, withInnerLabelPadding)
if err != nil {
return err
}
obj.Width = float64(go2.Max(defaultDims.Width, desiredWidth))
obj.Height = float64(go2.Max(defaultDims.Height, desiredHeight))
paddingX, paddingY := obj.GetPadding()
switch shapeType {
case d2target.ShapeSquare, d2target.ShapeCircle:
if desiredWidth != 0 || desiredHeight != 0 {
paddingX = 0.
paddingY = 0.
}
sideLength := math.Max(obj.Width+paddingX, obj.Height+paddingY)
obj.Width = sideLength
obj.Height = sideLength
default:
if dslShape == d2target.ShapeImage {
if desiredWidth == 0 {
obj.Width += float64(paddingX)
desiredWidth = defaultDims.Width
}
if desiredHeight == 0 {
obj.Height += float64(paddingY)
desiredHeight = defaultDims.Height
}
obj.Width = float64(go2.Max(MIN_SHAPE_SIZE, desiredWidth))
obj.Height = float64(go2.Max(MIN_SHAPE_SIZE, desiredHeight))
// images don't need further processing
continue
}
contentBox := geo.NewBox(geo.NewPoint(0, 0), float64(defaultDims.Width), float64(defaultDims.Height))
shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[dslShape]
s := shape.NewShape(shapeType, contentBox)
paddingX, paddingY := s.GetDefaultPadding()
if desiredWidth != 0 || desiredHeight != 0 {
paddingX = 0.
paddingY = 0.
} else {
// give shapes with icons extra padding to fit their label
if obj.Attributes.Icon != nil {
labelHeight := float64(labelDims.Height + INNER_LABEL_PADDING)
// Evenly pad enough to fit label above icon
paddingX += labelHeight
paddingY += labelHeight
}
switch shapeType {
case shape.TABLE_TYPE, shape.CLASS_TYPE, shape.CODE_TYPE, shape.IMAGE_TYPE:
default:
if obj.Attributes.Link != "" {
paddingX += 32
}
if obj.Attributes.Tooltip != "" {
paddingX += 32
}
}
}
fitWidth, fitHeight := s.GetDimensionsToFit(contentBox.Width, contentBox.Height, paddingX, paddingY)
obj.Width = math.Max(float64(desiredWidth), fitWidth)
obj.Height = math.Max(float64(desiredHeight), fitHeight)
if s.AspectRatio1() {
sideLength := math.Max(obj.Width, obj.Height)
obj.Width = sideLength
obj.Height = sideLength
} else if desiredHeight == 0 || desiredWidth == 0 {
if s.GetType() == shape.PERSON_TYPE {
obj.Width, obj.Height = shape.LimitAR(obj.Width, obj.Height, shape.PERSON_AR_LIMIT)
}
}
}
@ -1252,19 +1353,17 @@ func (g *Graph) Texts() []*d2target.MText {
}
func Key(k *d2ast.KeyPath) []string {
var ids []string
for _, s := range k.Path {
// We format each string of the key to ensure the resulting strings can be parsed
// correctly.
n := &d2ast.KeyPath{
Path: []*d2ast.StringBox{d2ast.MakeValueBox(d2ast.RawString(s.Unbox().ScalarString(), true)).StringBox()},
}
ids = append(ids, d2format.Format(n))
}
return ids
return d2format.KeyPath(k)
}
var ReservedKeywords = map[string]struct{}{
// All reserved keywords. See init below.
var ReservedKeywords map[string]struct{}
// All reserved keywords not including style keywords.
var ReservedKeywords2 map[string]struct{}
// Non Style/Holder keywords.
var SimpleReservedKeywords = map[string]struct{}{
"label": {},
"desc": {},
"shape": {},
@ -1331,15 +1430,88 @@ var NearConstantsArray = []string{
}
var NearConstants map[string]struct{}
// BoardKeywords contains the keywords that create new boards.
var BoardKeywords = map[string]struct{}{
"layers": {},
"scenarios": {},
"steps": {},
}
func init() {
ReservedKeywords = make(map[string]struct{})
for k, v := range SimpleReservedKeywords {
ReservedKeywords[k] = v
}
for k, v := range StyleKeywords {
ReservedKeywords[k] = v
}
for k, v := range ReservedKeywordHolders {
ReservedKeywords[k] = v
}
for k, v := range BoardKeywords {
ReservedKeywords[k] = v
}
ReservedKeywords2 = make(map[string]struct{})
for k, v := range SimpleReservedKeywords {
ReservedKeywords2[k] = v
}
for k, v := range ReservedKeywordHolders {
ReservedKeywords2[k] = v
}
for k, v := range BoardKeywords {
ReservedKeywords2[k] = v
}
NearConstants = make(map[string]struct{}, len(NearConstantsArray))
for _, k := range NearConstantsArray {
NearConstants[k] = struct{}{}
}
}
func (g *Graph) GetBoard(name string) *Graph {
for _, l := range g.Layers {
if l.Name == name {
return l
}
}
for _, l := range g.Scenarios {
if l.Name == name {
return l
}
}
for _, l := range g.Steps {
if l.Name == name {
return l
}
}
return nil
}
func (g *Graph) SortObjectsByAST() {
objects := append([]*Object(nil), g.Objects...)
sort.Slice(objects, func(i, j int) bool {
o1 := objects[i]
o2 := objects[j]
if len(o1.References) == 0 || len(o2.References) == 0 {
return i < j
}
r1 := o1.References[0]
r2 := o2.References[0]
return r1.Key.Path[r1.KeyPathIndex].Unbox().GetRange().Before(r2.Key.Path[r2.KeyPathIndex].Unbox().GetRange())
})
g.Objects = objects
}
func (g *Graph) SortEdgesByAST() {
edges := append([]*Edge(nil), g.Edges...)
sort.Slice(edges, func(i, j int) bool {
e1 := edges[i]
e2 := edges[j]
if len(e1.References) == 0 || len(e2.References) == 0 {
return i < j
}
return e1.References[0].Edge.Range.Before(e2.References[0].Edge.Range)
})
g.Edges = edges
}

View file

@ -3,7 +3,7 @@ package d2graph
import "oss.terrastruct.com/d2/d2target"
func (obj *Object) IsSequenceDiagram() bool {
return obj != nil && obj.Attributes.Shape.Value == d2target.ShapeSequenceDiagram
return obj != nil && obj.Attributes != nil && obj.Attributes.Shape.Value == d2target.ShapeSequenceDiagram
}
func (obj *Object) OuterSequenceDiagram() *Object {
@ -65,7 +65,7 @@ func (obj *Object) ContainsAnyObject(objects []*Object) bool {
func (o *Object) ContainedBy(obj *Object) bool {
for _, ref := range o.References {
curr := ref.UnresolvedScopeObj
curr := ref.ScopeObj
for curr != nil {
if curr == obj {
return true

252
d2ir/compile.go Normal file
View file

@ -0,0 +1,252 @@
package d2ir
import (
"oss.terrastruct.com/d2/d2ast"
"oss.terrastruct.com/d2/d2parser"
)
type compiler struct {
err d2parser.ParseError
}
func (c *compiler) errorf(n d2ast.Node, f string, v ...interface{}) {
c.err.Errors = append(c.err.Errors, d2parser.Errorf(n, f, v...).(d2ast.Error))
}
func Compile(ast *d2ast.Map) (*Map, error) {
c := &compiler{}
m := &Map{}
m.initRoot()
m.parent.(*Field).References[0].Context.Scope = ast
c.compileMap(m, ast)
c.compileScenarios(m)
c.compileSteps(m)
if !c.err.Empty() {
return nil, c.err
}
return m, nil
}
func (c *compiler) compileScenarios(m *Map) {
scenariosf := m.GetField("scenarios")
if scenariosf == nil {
return
}
scenarios := scenariosf.Map()
if scenarios == nil {
return
}
for _, sf := range scenarios.Fields {
if sf.Map() == nil {
continue
}
base := m.CopyBase(sf)
OverlayMap(base, sf.Map())
sf.Composite = base
c.compileScenarios(sf.Map())
c.compileSteps(sf.Map())
}
}
func (c *compiler) compileSteps(m *Map) {
stepsf := m.GetField("steps")
if stepsf == nil {
return
}
steps := stepsf.Map()
if steps == nil {
return
}
for i, sf := range steps.Fields {
if sf.Map() == nil {
continue
}
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) {
for _, n := range ast.Nodes {
switch {
case n.MapKey != nil:
c.compileKey(&RefContext{
Key: n.MapKey,
Scope: ast,
ScopeMap: dst,
})
case n.Substitution != nil:
panic("TODO")
}
}
}
func (c *compiler) compileKey(refctx *RefContext) {
if len(refctx.Key.Edges) == 0 {
c.compileField(refctx.ScopeMap, refctx.Key.Key, refctx)
} else {
c.compileEdges(refctx)
}
}
func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext) {
f, err := dst.EnsureField(kp, refctx)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
return
}
if refctx.Key.Primary.Unbox() != nil {
f.Primary_ = &Scalar{
parent: f,
Value: refctx.Key.Primary.Unbox(),
}
}
if refctx.Key.Value.Array != nil {
a := &Array{
parent: f,
}
c.compileArray(a, refctx.Key.Value.Array)
f.Composite = a
} else if refctx.Key.Value.Map != nil {
if f.Map() == nil {
f.Composite = &Map{
parent: f,
}
}
c.compileMap(f.Map(), refctx.Key.Value.Map)
} else if refctx.Key.Value.ScalarBox().Unbox() != nil {
f.Primary_ = &Scalar{
parent: f,
Value: refctx.Key.Value.ScalarBox().Unbox(),
}
}
}
func (c *compiler) compileEdges(refctx *RefContext) {
if refctx.Key.Key != nil {
f, err := refctx.ScopeMap.EnsureField(refctx.Key.Key, refctx)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
return
}
if _, ok := f.Composite.(*Array); ok {
c.errorf(refctx.Key.Key, "cannot index into array")
return
}
if f.Map() == nil {
f.Composite = &Map{
parent: f,
}
}
refctx.ScopeMap = f.Map()
}
eida := NewEdgeIDs(refctx.Key)
for i, eid := range eida {
refctx = refctx.Copy()
refctx.Edge = refctx.Key.Edges[i]
var e *Edge
if eid.Index != nil {
ea := refctx.ScopeMap.GetEdges(eid)
if len(ea) == 0 {
c.errorf(refctx.Edge, "indexed edge does not exist")
continue
}
e = ea[0]
e.References = append(e.References, &EdgeReference{
Context: refctx,
})
refctx.ScopeMap.appendFieldReferences(0, refctx.Edge.Src, refctx)
refctx.ScopeMap.appendFieldReferences(0, refctx.Edge.Dst, refctx)
} else {
_, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, refctx)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
continue
}
_, err = refctx.ScopeMap.EnsureField(refctx.Edge.Dst, refctx)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
continue
}
e, err = refctx.ScopeMap.CreateEdge(eid, refctx)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
continue
}
}
if refctx.Key.EdgeKey != nil {
if e.Map_ == nil {
e.Map_ = &Map{
parent: e,
}
}
c.compileField(e.Map_, refctx.Key.EdgeKey, refctx)
} else {
if refctx.Key.Primary.Unbox() != nil {
e.Primary_ = &Scalar{
parent: e,
Value: refctx.Key.Primary.Unbox(),
}
}
if refctx.Key.Value.Array != nil {
c.errorf(refctx.Key.Value.Unbox(), "edges cannot be assigned arrays")
continue
} else if refctx.Key.Value.Map != nil {
if e.Map_ == nil {
e.Map_ = &Map{
parent: e,
}
}
c.compileMap(e.Map_, refctx.Key.Value.Map)
} else if refctx.Key.Value.ScalarBox().Unbox() != nil {
e.Primary_ = &Scalar{
parent: e,
Value: refctx.Key.Value.ScalarBox().Unbox(),
}
}
}
}
}
func (c *compiler) compileArray(dst *Array, a *d2ast.Array) {
for _, an := range a.Nodes {
var irv Value
switch v := an.Unbox().(type) {
case *d2ast.Array:
ira := &Array{
parent: dst,
}
c.compileArray(ira, v)
irv = ira
case *d2ast.Map:
irm := &Map{
parent: dst,
}
c.compileMap(irm, v)
irv = irm
case d2ast.Scalar:
irv = &Scalar{
parent: dst,
Value: v,
}
case *d2ast.Substitution:
// panic("TODO")
}
dst.Values = append(dst.Values, irv)
}
}

476
d2ir/compile_test.go Normal file
View file

@ -0,0 +1,476 @@
package d2ir_test
import (
"fmt"
"math/big"
"path/filepath"
"strings"
"testing"
"oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/util-go/diff"
"oss.terrastruct.com/d2/d2ast"
"oss.terrastruct.com/d2/d2ir"
"oss.terrastruct.com/d2/d2parser"
)
func TestCompile(t *testing.T) {
t.Parallel()
t.Run("fields", testCompileFields)
t.Run("edges", testCompileEdges)
t.Run("layers", testCompileLayers)
t.Run("scenarios", testCompileScenarios)
t.Run("steps", testCompileSteps)
}
type testCase struct {
name string
run func(testing.TB)
}
func runa(t *testing.T, tca []testCase) {
for _, tc := range tca {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
tc.run(t)
})
}
}
func compile(t testing.TB, text string) (*d2ir.Map, error) {
t.Helper()
d2Path := fmt.Sprintf("%v.d2", t.Name())
ast, err := d2parser.Parse(d2Path, strings.NewReader(text), nil)
assert.Success(t, err)
m, err := d2ir.Compile(ast)
if err != nil {
return nil, err
}
err = diff.TestdataJSON(filepath.Join("..", "testdata", "d2ir", t.Name()), m)
if err != nil {
return nil, err
}
return m, nil
}
func assertQuery(t testing.TB, n d2ir.Node, nfields, nedges int, primary interface{}, idStr string) d2ir.Node {
t.Helper()
m := n.Map()
p := n.Primary()
if idStr != "" {
var err error
n, err = m.Query(idStr)
assert.Success(t, err)
assert.NotEqual(t, n, nil)
p = n.Primary()
m = n.Map()
}
assert.Equal(t, nfields, m.FieldCountRecursive())
assert.Equal(t, nedges, m.EdgeCountRecursive())
if !makeScalar(p).Equal(makeScalar(primary)) {
t.Fatalf("expected primary %#v but got %s", primary, p)
}
return n
}
func makeScalar(v interface{}) *d2ir.Scalar {
s := &d2ir.Scalar{}
switch v := v.(type) {
case *d2ir.Scalar:
if v == nil {
s.Value = &d2ast.Null{}
return s
}
return v
case bool:
s.Value = &d2ast.Boolean{
Value: v,
}
case float64:
bv := &big.Rat{}
bv.SetFloat64(v)
s.Value = &d2ast.Number{
Value: bv,
}
case int:
s.Value = &d2ast.Number{
Value: big.NewRat(int64(v), 1),
}
case string:
s.Value = d2ast.FlatDoubleQuotedString(v)
default:
if v != nil {
panic(fmt.Sprintf("d2ir: unexpected type to makeScalar: %#v", v))
}
s.Value = &d2ast.Null{}
}
return s
}
func testCompileFields(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "root",
run: func(t testing.TB) {
m, err := compile(t, `x`)
assert.Success(t, err)
assertQuery(t, m, 1, 0, nil, "")
assertQuery(t, m, 0, 0, nil, "x")
},
},
{
name: "label",
run: func(t testing.TB) {
m, err := compile(t, `x: yes`)
assert.Success(t, err)
assertQuery(t, m, 1, 0, nil, "")
assertQuery(t, m, 0, 0, "yes", "x")
},
},
{
name: "nested",
run: func(t testing.TB) {
m, err := compile(t, `x.y: yes`)
assert.Success(t, err)
assertQuery(t, m, 2, 0, nil, "")
assertQuery(t, m, 1, 0, nil, "x")
assertQuery(t, m, 0, 0, "yes", "x.y")
},
},
{
name: "array",
run: func(t testing.TB) {
m, err := compile(t, `x: [1;2;3;4]`)
assert.Success(t, err)
assertQuery(t, m, 1, 0, nil, "")
f := assertQuery(t, m, 0, 0, nil, "x").(*d2ir.Field)
assert.String(t, `[1; 2; 3; 4]`, f.Composite.String())
},
},
{
name: "null",
run: func(t testing.TB) {
m, err := compile(t, `pq: pq
pq: null`)
assert.Success(t, err)
assertQuery(t, m, 1, 0, nil, "")
// null doesn't delete pq from *Map so that for language tooling
// we maintain the references.
// Instead d2compiler will ensure it doesn't get rendered.
assertQuery(t, m, 0, 0, nil, "pq")
},
},
}
runa(t, tca)
t.Run("primary", func(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "root",
run: func(t testing.TB) {
m, err := compile(t, `x: yes { pqrs }`)
assert.Success(t, err)
assertQuery(t, m, 2, 0, nil, "")
assertQuery(t, m, 1, 0, "yes", "x")
assertQuery(t, m, 0, 0, nil, "x.pqrs")
},
},
{
name: "nested",
run: func(t testing.TB) {
m, err := compile(t, `x.y: yes { pqrs }`)
assert.Success(t, err)
assertQuery(t, m, 3, 0, nil, "")
assertQuery(t, m, 2, 0, nil, "x")
assertQuery(t, m, 1, 0, "yes", "x.y")
assertQuery(t, m, 0, 0, nil, "x.y.pqrs")
},
},
}
runa(t, tca)
})
}
func testCompileEdges(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "root",
run: func(t testing.TB) {
m, err := compile(t, `x -> y`)
assert.Success(t, err)
assertQuery(t, m, 2, 1, nil, "")
assertQuery(t, m, 0, 0, nil, `(x -> y)[0]`)
assertQuery(t, m, 0, 0, nil, "x")
assertQuery(t, m, 0, 0, nil, "y")
},
},
{
name: "nested",
run: func(t testing.TB) {
m, err := compile(t, `x.y -> z.p`)
assert.Success(t, err)
assertQuery(t, m, 4, 1, nil, "")
assertQuery(t, m, 1, 0, nil, "x")
assertQuery(t, m, 0, 0, nil, "x.y")
assertQuery(t, m, 1, 0, nil, "z")
assertQuery(t, m, 0, 0, nil, "z.p")
assertQuery(t, m, 0, 0, nil, "(x.y -> z.p)[0]")
},
},
{
name: "underscore",
run: func(t testing.TB) {
m, err := compile(t, `p: { _.x -> z }`)
assert.Success(t, err)
assertQuery(t, m, 3, 1, nil, "")
assertQuery(t, m, 0, 0, nil, "x")
assertQuery(t, m, 1, 0, nil, "p")
assertQuery(t, m, 0, 0, nil, "(x -> p.z)[0]")
},
},
{
name: "chain",
run: func(t testing.TB) {
m, err := compile(t, `a -> b -> c -> d`)
assert.Success(t, err)
assertQuery(t, m, 4, 3, nil, "")
assertQuery(t, m, 0, 0, nil, "a")
assertQuery(t, m, 0, 0, nil, "b")
assertQuery(t, m, 0, 0, nil, "c")
assertQuery(t, m, 0, 0, nil, "d")
assertQuery(t, m, 0, 0, nil, "(a -> b)[0]")
assertQuery(t, m, 0, 0, nil, "(b -> c)[0]")
assertQuery(t, m, 0, 0, nil, "(c -> d)[0]")
},
},
}
runa(t, tca)
t.Run("errs", func(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "bad_edge",
run: func(t testing.TB) {
_, err := compile(t, `(x -> y): { p -> q }`)
assert.ErrorString(t, err, `TestCompile/edges/errs/bad_edge.d2:1:13: cannot create edge inside edge`)
},
},
}
runa(t, tca)
})
}
func testCompileLayers(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "root",
run: func(t testing.TB) {
m, err := compile(t, `x -> y
layers: {
bingo: { p.q.z }
}`)
assert.Success(t, err)
assertQuery(t, m, 7, 1, nil, "")
assertQuery(t, m, 0, 0, nil, `(x -> y)[0]`)
assertQuery(t, m, 0, 0, nil, "x")
assertQuery(t, m, 0, 0, nil, "y")
assertQuery(t, m, 3, 0, nil, "layers.bingo")
},
},
}
runa(t, tca)
t.Run("errs", func(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "1/bad_edge",
run: func(t testing.TB) {
_, err := compile(t, `layers.x -> layers.y`)
assert.ErrorString(t, err, `TestCompile/layers/errs/1/bad_edge.d2:1:1: cannot create edges between boards`)
},
},
{
name: "2/bad_edge",
run: func(t testing.TB) {
_, err := compile(t, `layers -> scenarios`)
assert.ErrorString(t, err, `TestCompile/layers/errs/2/bad_edge.d2:1:1: edge with board keyword alone doesn't make sense`)
},
},
{
name: "3/bad_edge",
run: func(t testing.TB) {
_, err := compile(t, `layers.x.y -> steps.z.p`)
assert.ErrorString(t, err, `TestCompile/layers/errs/3/bad_edge.d2:1:1: cannot create edges between boards`)
},
},
{
name: "4/good_edge",
run: func(t testing.TB) {
_, err := compile(t, `layers.x.y -> layers.x.y`)
assert.Success(t, err)
},
},
}
runa(t, tca)
})
}
func testCompileScenarios(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "root",
run: func(t testing.TB) {
m, err := compile(t, `x -> y
scenarios: {
bingo: { p.q.z }
nuclear: { quiche }
}`)
assert.Success(t, err)
assertQuery(t, m, 13, 3, nil, "")
assertQuery(t, m, 0, 0, nil, "x")
assertQuery(t, m, 0, 0, nil, "y")
assertQuery(t, m, 0, 0, nil, `(x -> y)[0]`)
assertQuery(t, m, 5, 1, nil, "scenarios.bingo")
assertQuery(t, m, 0, 0, nil, "scenarios.bingo.x")
assertQuery(t, m, 0, 0, nil, "scenarios.bingo.y")
assertQuery(t, m, 0, 0, nil, `scenarios.bingo.(x -> y)[0]`)
assertQuery(t, m, 2, 0, nil, "scenarios.bingo.p")
assertQuery(t, m, 1, 0, nil, "scenarios.bingo.p.q")
assertQuery(t, m, 0, 0, nil, "scenarios.bingo.p.q.z")
assertQuery(t, m, 3, 1, nil, "scenarios.nuclear")
assertQuery(t, m, 0, 0, nil, "scenarios.nuclear.x")
assertQuery(t, m, 0, 0, nil, "scenarios.nuclear.y")
assertQuery(t, m, 0, 0, nil, `scenarios.nuclear.(x -> y)[0]`)
assertQuery(t, m, 0, 0, nil, "scenarios.nuclear.quiche")
},
},
}
runa(t, tca)
}
func testCompileSteps(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "root",
run: func(t testing.TB) {
m, err := compile(t, `x -> y
steps: {
bingo: { p.q.z }
nuclear: { quiche }
}`)
assert.Success(t, err)
assertQuery(t, m, 16, 3, nil, "")
assertQuery(t, m, 0, 0, nil, "x")
assertQuery(t, m, 0, 0, nil, "y")
assertQuery(t, m, 0, 0, nil, `(x -> y)[0]`)
assertQuery(t, m, 5, 1, nil, "steps.bingo")
assertQuery(t, m, 0, 0, nil, "steps.bingo.x")
assertQuery(t, m, 0, 0, nil, "steps.bingo.y")
assertQuery(t, m, 0, 0, nil, `steps.bingo.(x -> y)[0]`)
assertQuery(t, m, 2, 0, nil, "steps.bingo.p")
assertQuery(t, m, 1, 0, nil, "steps.bingo.p.q")
assertQuery(t, m, 0, 0, nil, "steps.bingo.p.q.z")
assertQuery(t, m, 6, 1, nil, "steps.nuclear")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.x")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.y")
assertQuery(t, m, 0, 0, nil, `steps.nuclear.(x -> y)[0]`)
assertQuery(t, m, 2, 0, nil, "steps.nuclear.p")
assertQuery(t, m, 1, 0, nil, "steps.nuclear.p.q")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.p.q.z")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.quiche")
},
},
{
name: "recursive",
run: func(t testing.TB) {
m, err := compile(t, `x -> y
steps: {
bingo: { p.q.z }
nuclear: {
quiche
scenarios: {
bavarian: {
perseverance
}
}
}
}`)
assert.Success(t, err)
assertQuery(t, m, 25, 4, nil, "")
assertQuery(t, m, 0, 0, nil, "x")
assertQuery(t, m, 0, 0, nil, "y")
assertQuery(t, m, 0, 0, nil, `(x -> y)[0]`)
assertQuery(t, m, 5, 1, nil, "steps.bingo")
assertQuery(t, m, 0, 0, nil, "steps.bingo.x")
assertQuery(t, m, 0, 0, nil, "steps.bingo.y")
assertQuery(t, m, 0, 0, nil, `steps.bingo.(x -> y)[0]`)
assertQuery(t, m, 2, 0, nil, "steps.bingo.p")
assertQuery(t, m, 1, 0, nil, "steps.bingo.p.q")
assertQuery(t, m, 0, 0, nil, "steps.bingo.p.q.z")
assertQuery(t, m, 15, 2, nil, "steps.nuclear")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.x")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.y")
assertQuery(t, m, 0, 0, nil, `steps.nuclear.(x -> y)[0]`)
assertQuery(t, m, 2, 0, nil, "steps.nuclear.p")
assertQuery(t, m, 1, 0, nil, "steps.nuclear.p.q")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.p.q.z")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.quiche")
assertQuery(t, m, 7, 1, nil, "steps.nuclear.scenarios.bavarian")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.scenarios.bavarian.x")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.scenarios.bavarian.y")
assertQuery(t, m, 0, 0, nil, `steps.nuclear.scenarios.bavarian.(x -> y)[0]`)
assertQuery(t, m, 2, 0, nil, "steps.nuclear.scenarios.bavarian.p")
assertQuery(t, m, 1, 0, nil, "steps.nuclear.scenarios.bavarian.p.q")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.scenarios.bavarian.p.q.z")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.scenarios.bavarian.quiche")
assertQuery(t, m, 0, 0, nil, "steps.nuclear.scenarios.bavarian.perseverance")
},
},
}
runa(t, tca)
}

1061
d2ir/d2ir.go Normal file

File diff suppressed because it is too large Load diff

69
d2ir/d2ir_test.go Normal file
View file

@ -0,0 +1,69 @@
package d2ir_test
import (
"testing"
"oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/d2/d2ast"
"oss.terrastruct.com/d2/d2ir"
)
func TestCopy(t *testing.T) {
t.Parallel()
const scalStr = `Those who claim the dead never return to life haven't ever been around.`
s := &d2ir.Scalar{
Value: d2ast.FlatUnquotedString(scalStr),
}
a := &d2ir.Array{
Values: []d2ir.Value{
&d2ir.Scalar{
Value: &d2ast.Boolean{
Value: true,
},
},
},
}
m2 := &d2ir.Map{
Fields: []*d2ir.Field{
{Primary_: s},
},
}
const keyStr = `Absence makes the heart grow frantic.`
f := &d2ir.Field{
Name: keyStr,
Primary_: s,
Composite: a,
}
e := &d2ir.Edge{
Primary_: s,
Map_: m2,
}
m := &d2ir.Map{
Fields: []*d2ir.Field{f},
Edges: []*d2ir.Edge{e},
}
m = m.Copy(nil).(*d2ir.Map)
f.Name = `Many a wife thinks her husband is the world's greatest lover.`
assert.Equal(t, m, m.Fields[0].Parent())
assert.Equal(t, keyStr, m.Fields[0].Name)
assert.Equal(t, m.Fields[0], m.Fields[0].Primary_.Parent())
assert.Equal(t, m.Fields[0], m.Fields[0].Composite.(*d2ir.Array).Parent())
assert.Equal(t,
m.Fields[0].Composite,
m.Fields[0].Composite.(*d2ir.Array).Values[0].(*d2ir.Scalar).Parent(),
)
assert.Equal(t, m, m.Edges[0].Parent())
assert.Equal(t, m.Edges[0], m.Edges[0].Primary_.Parent())
assert.Equal(t, m.Edges[0], m.Edges[0].Map_.Parent())
assert.Equal(t, m.Edges[0].Map_, m.Edges[0].Map_.Fields[0].Parent())
assert.Equal(t, m.Edges[0].Map_.Fields[0], m.Edges[0].Map_.Fields[0].Primary_.Parent())
}

52
d2ir/merge.go Normal file
View file

@ -0,0 +1,52 @@
package d2ir
func OverlayMap(base, overlay *Map) {
for _, of := range overlay.Fields {
bf := base.GetField(of.Name)
if bf == nil {
base.Fields = append(base.Fields, of.Copy(base).(*Field))
continue
}
OverlayField(bf, of)
}
for _, oe := range overlay.Edges {
bea := base.GetEdges(oe.ID)
if len(bea) == 0 {
base.Edges = append(base.Edges, oe.Copy(base).(*Edge))
continue
}
be := bea[0]
OverlayEdge(be, oe)
}
}
func OverlayField(bf, of *Field) {
if of.Primary_ != nil {
bf.Primary_ = of.Primary_.Copy(bf).(*Scalar)
}
if of.Composite != nil {
if bf.Map() != nil && of.Map() != nil {
OverlayMap(bf.Map(), of.Map())
} else {
bf.Composite = of.Composite.Copy(bf).(*Map)
}
}
bf.References = append(bf.References, of.References...)
}
func OverlayEdge(be, oe *Edge) {
if oe.Primary_ != nil {
be.Primary_ = oe.Primary_.Copy(be).(*Scalar)
}
if oe.Map_ != nil {
if be.Map_ != nil {
OverlayMap(be.Map(), oe.Map_)
} else {
be.Map_ = oe.Map_.Copy(be).(*Map)
}
}
be.References = append(be.References, oe.References...)
}

62
d2ir/query.go Normal file
View file

@ -0,0 +1,62 @@
package d2ir
import (
"fmt"
"oss.terrastruct.com/d2/d2parser"
)
// QueryAll is only for tests and debugging.
func (m *Map) QueryAll(idStr string) (na []Node, _ error) {
k, err := d2parser.ParseMapKey(idStr)
if err != nil {
return nil, err
}
if k.Key != nil {
f := m.GetField(k.Key.IDA()...)
if f == nil {
return nil, nil
}
if len(k.Edges) == 0 {
na = append(na, f)
return na, nil
}
m = f.Map()
if m == nil {
return nil, nil
}
}
eida := NewEdgeIDs(k)
for _, eid := range eida {
ea := m.GetEdges(eid)
for _, e := range ea {
if k.EdgeKey == nil {
na = append(na, e)
} else if e.Map_ != nil {
f := e.Map_.GetField(k.EdgeKey.IDA()...)
if f != nil {
na = append(na, f)
}
}
}
}
return na, nil
}
// Query is only for tests and debugging.
func (m *Map) Query(idStr string) (Node, error) {
na, err := m.QueryAll(idStr)
if err != nil {
return nil, err
}
if len(na) == 0 {
return nil, nil
}
if len(na) > 1 {
return nil, fmt.Errorf("expected only one query result but got: %#v", err)
}
return na[0], nil
}

View file

@ -5,11 +5,12 @@ import (
"sort"
"strings"
"oss.terrastruct.com/util-go/go2"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/label"
"oss.terrastruct.com/util-go/go2"
)
func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]*sequenceDiagram, map[string]int, map[string]int, error) {
@ -113,6 +114,7 @@ func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) (*sequenceDiag
func getLayoutEdges(g *d2graph.Graph, toRemove map[*d2graph.Edge]struct{}) ([]*d2graph.Edge, map[string]int) {
edgeOrder := make(map[string]int)
layoutEdges := make([]*d2graph.Edge, 0, len(g.Edges)-len(toRemove))
for i, edge := range g.Edges {
edgeOrder[edge.AbsID()] = i
if _, exists := toRemove[edge]; !exists {

View file

@ -377,7 +377,7 @@ container -> c: edge 1
}
func TestSelfEdges(t *testing.T) {
g := d2graph.NewGraph(nil)
g := d2graph.NewGraph()
g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram}
n1 := g.Root.EnsureChild([]string{"n1"})
n1.Box = geo.NewBox(nil, 100, 100)
@ -387,7 +387,7 @@ func TestSelfEdges(t *testing.T) {
Src: n1,
Dst: n1,
Index: 0,
Attributes: d2graph.Attributes{
Attributes: &d2graph.Attributes{
Label: d2graph.Scalar{Value: "left to right"},
},
},
@ -413,11 +413,11 @@ func TestSelfEdges(t *testing.T) {
}
func TestSequenceToDescendant(t *testing.T) {
g := d2graph.NewGraph(nil)
g := d2graph.NewGraph()
g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram}
a := g.Root.EnsureChild([]string{"a"})
a.Box = geo.NewBox(nil, 100, 100)
a.Attributes = d2graph.Attributes{
a.Attributes = &d2graph.Attributes{
Shape: d2graph.Scalar{Value: shape.PERSON_TYPE},
}
a_t1 := a.EnsureChild([]string{"t1"})
@ -425,13 +425,15 @@ func TestSequenceToDescendant(t *testing.T) {
g.Edges = []*d2graph.Edge{
{
Src: a,
Dst: a_t1,
Index: 0,
Src: a,
Dst: a_t1,
Index: 0,
Attributes: &d2graph.Attributes{},
}, {
Src: a_t1,
Dst: a,
Index: 0,
Src: a_t1,
Dst: a,
Index: 0,
Attributes: &d2graph.Attributes{},
},
}

View file

@ -105,6 +105,12 @@ func newSequenceDiagram(objects []*d2graph.Object, messages []*d2graph.Edge) *se
sd.objectRank[actor] = rank
if actor.Width < MIN_ACTOR_WIDTH {
dslShape := strings.ToLower(actor.Attributes.Shape.Value)
switch dslShape {
case d2target.ShapePerson, d2target.ShapeSquare, d2target.ShapeCircle:
// scale shape up to min width uniformly
actor.Height *= MIN_ACTOR_WIDTH / actor.Width
}
actor.Width = MIN_ACTOR_WIDTH
}
sd.maxActorHeight = math.Max(sd.maxActorHeight, actor.Height)
@ -225,7 +231,7 @@ func (sd *sequenceDiagram) placeGroup(group *d2graph.Object) {
for _, n := range sd.notes {
inGroup := false
for _, ref := range n.References {
curr := ref.UnresolvedScopeObj
curr := ref.ScopeObj
for curr != nil {
if curr == group {
inGroup = true
@ -324,7 +330,7 @@ func (sd *sequenceDiagram) addLifelineEdges() {
actorLifelineEnd := actor.Center()
actorLifelineEnd.Y = endY
sd.lifelines = append(sd.lifelines, &d2graph.Edge{
Attributes: d2graph.Attributes{
Attributes: &d2graph.Attributes{
Style: d2graph.Style{
StrokeDash: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_DASH)},
StrokeWidth: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_WIDTH)},

View file

@ -44,32 +44,65 @@ func Compile(ctx context.Context, input string, opts *CompileOptions) (*d2target
return nil, nil, err
}
d, err := compile(ctx, g, opts)
if err != nil {
return nil, nil, err
}
return d, g, nil
}
func compile(ctx context.Context, g *d2graph.Graph, opts *CompileOptions) (*d2target.Diagram, error) {
if len(g.Objects) > 0 {
err = g.SetDimensions(opts.MeasuredTexts, opts.Ruler, opts.FontFamily)
err := g.SetDimensions(opts.MeasuredTexts, opts.Ruler, opts.FontFamily)
if err != nil {
return nil, nil, err
return nil, err
}
coreLayout, err := getLayout(opts)
if err != nil {
return nil, nil, err
return nil, err
}
constantNears := d2near.WithoutConstantNears(ctx, g)
err = d2sequence.Layout(ctx, g, coreLayout)
if err != nil {
return nil, nil, err
return nil, err
}
err = d2near.Layout(ctx, g, constantNears)
if err != nil {
return nil, nil, err
return nil, err
}
}
diagram, err := d2exporter.Export(ctx, g, opts.ThemeID, opts.FontFamily)
return diagram, g, err
d, err := d2exporter.Export(ctx, g, opts.ThemeID, opts.FontFamily)
if err != nil {
return nil, err
}
for _, l := range g.Layers {
ld, err := compile(ctx, l, opts)
if err != nil {
return nil, err
}
d.Layers = append(d.Layers, ld)
}
for _, l := range g.Scenarios {
ld, err := compile(ctx, l, opts)
if err != nil {
return nil, err
}
d.Scenarios = append(d.Scenarios, ld)
}
for _, l := range g.Steps {
ld, err := compile(ctx, l, opts)
if err != nil {
return nil, err
}
d.Steps = append(d.Steps, ld)
}
return d, nil
}
func getLayout(opts *CompileOptions) (func(context.Context, *d2graph.Graph) error, error) {

View file

@ -396,7 +396,6 @@ func Delete(g *d2graph.Graph, key string) (_ *d2graph.Graph, err error) {
if g != g2 {
return g2, nil
}
g = g2
if len(mk.Edges) == 1 {
obj := g.Root
@ -1109,7 +1108,7 @@ func move(g *d2graph.Graph, key, newKey string) (*d2graph.Graph, error) {
Key: detachedMK.Key,
MapKey: detachedMK,
Scope: mostNestedRef.Scope,
}, mostNestedRef.UnresolvedScopeObj)
}, mostNestedRef.ScopeObj)
}
}
@ -1284,8 +1283,8 @@ func move(g *d2graph.Graph, key, newKey string) (*d2graph.Graph, error) {
// We don't want this to be underscore-resolved scope. We want to ignore underscores
var scopeak []string
if ref.UnresolvedScopeObj != g.Root {
scopek, err := d2parser.ParseKey(ref.UnresolvedScopeObj.AbsID())
if ref.ScopeObj != g.Root {
scopek, err := d2parser.ParseKey(ref.ScopeObj.AbsID())
if err != nil {
return nil, err
}

View file

@ -1373,12 +1373,12 @@ more.(ok.q.z -> p.k): "furbling, v.:"
{
name: "complex_edge_1",
text: `a.b.(x -> y).q.z
text: `a.b.(x -> y).style.animated
`,
key: "a.b",
newName: "ooo",
exp: `a.ooo.(x -> y).q.z
exp: `a.ooo.(x -> y).style.animated
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
if len(g.Objects) != 4 {
@ -1392,12 +1392,12 @@ more.(ok.q.z -> p.k): "furbling, v.:"
{
name: "complex_edge_2",
text: `a.b.(x -> y).q.z
text: `a.b.(x -> y).style.animated
`,
key: "a.b.x",
newName: "papa",
exp: `a.b.(papa -> y).q.z
exp: `a.b.(papa -> y).style.animated
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
if len(g.Objects) != 4 {
@ -1454,12 +1454,12 @@ more.(ok.q.z -> p.k): "furbling, v.:"
{
name: "arrows_complex",
text: `a.b.(x -- y).q.z
text: `a.b.(x -- y).style.animated
`,
key: "a.b.(x -- y)[0]",
newName: "(x <-> y)[0]",
exp: `a.b.(x <-> y).q.z
exp: `a.b.(x <-> y).style.animated
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
if len(g.Objects) != 4 {
@ -3025,7 +3025,7 @@ d
if err == nil {
objectsAfter := len(g.Objects)
if objectsBefore != objectsAfter {
println(d2format.Format(g.AST))
t.Log(d2format.Format(g.AST))
return nil, fmt.Errorf("move cannot destroy or create objects: found %d objects before and %d objects after", objectsBefore, objectsAfter)
}
}

View file

@ -45,7 +45,7 @@ func Parse(path string, r io.RuneReader, opts *ParseOptions) (*d2ast.Map, error)
}
m := p.parseMap(true)
if !p.err.empty() {
if !p.err.Empty() {
return m, p.err
}
return m, nil
@ -57,7 +57,7 @@ func ParseKey(key string) (*d2ast.KeyPath, error) {
}
k := p.parseKey()
if !p.err.empty() {
if !p.err.Empty() {
return nil, fmt.Errorf("failed to parse key %q: %w", key, p.err)
}
if k == nil {
@ -72,7 +72,7 @@ func ParseMapKey(mapKey string) (*d2ast.Key, error) {
}
mk := p.parseMapKey()
if !p.err.empty() {
if !p.err.Empty() {
return nil, fmt.Errorf("failed to parse map key %q: %w", mapKey, p.err)
}
if mk == nil {
@ -87,7 +87,7 @@ func ParseValue(value string) (d2ast.Value, error) {
}
v := p.parseValue()
if !p.err.empty() {
if !p.err.Empty() {
return nil, fmt.Errorf("failed to parse value %q: %w", value, p.err)
}
if v.Unbox() == nil {
@ -130,7 +130,16 @@ type ParseError struct {
Errors []d2ast.Error `json:"errs"`
}
func (pe ParseError) empty() bool {
func Errorf(n d2ast.Node, f string, v ...interface{}) error {
f = "%v: " + f
v = append([]interface{}{n.GetRange()}, v...)
return d2ast.Error{
Range: n.GetRange(),
Message: fmt.Sprintf(f, v...),
}
}
func (pe ParseError) Empty() bool {
return pe.IOError == nil && len(pe.Errors) == 0
}
@ -138,11 +147,12 @@ func (pe ParseError) Error() string {
var sb strings.Builder
if pe.IOError != nil {
sb.WriteString(pe.IOError.Error())
sb.WriteByte('\n')
}
for _, err := range pe.Errors {
for i, err := range pe.Errors {
if pe.IOError != nil || i > 0 {
sb.WriteByte('\n')
}
sb.WriteString(err.Error())
sb.WriteByte('\n')
}
return sb.String()
}

View file

@ -63,7 +63,7 @@ func TestSketch(t *testing.T) {
}
People discovery: "People discovery \nservice"
admixer: Ad mixer {
fill: "#c1a2f3"
style.fill: "#c1a2f3"
}
onboarding service: "Onboarding \nservice"
@ -107,7 +107,7 @@ Android: {
web -> twitter fe
timeline scorer: "Timeline\nScorer" {
fill: "#ffdef1"
style.fill "#ffdef1"
}
home ranker: Home Ranker
@ -119,7 +119,7 @@ timeline mixer -> home ranker: {
}
timeline mixer -> timeline service
home mixer: Home mixer {
# fill: "#c1a2f3"
# style.fill "#c1a2f3"
}
container0.graphql -> home mixer: {
style.stroke-dash: 4
@ -146,7 +146,7 @@ prediction service2: Prediction Service {
icon: https://cdn-icons-png.flaticon.com/512/6461/6461819.png
}
home scorer: Home Scorer {
fill: "#ffdef1"
style.fill "#ffdef1"
}
manhattan: Manhattan
memcache: Memcache {
@ -154,15 +154,15 @@ memcache: Memcache {
}
fetch: Fetch {
multiple: true
style.multiple: true
shape: step
}
feature: Feature {
multiple: true
style.multiple: true
shape: step
}
scoring: Scoring {
multiple: true
style.multiple: true
shape: step
}
fetch -> feature

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 271 KiB

After

Width:  |  Height:  |  Size: 267 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 253 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 303 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 248 KiB

After

Width:  |  Height:  |  Size: 248 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 246 KiB

After

Width:  |  Height:  |  Size: 246 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 310 KiB

After

Width:  |  Height:  |  Size: 309 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 388 KiB

After

Width:  |  Height:  |  Size: 387 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 803 KiB

After

Width:  |  Height:  |  Size: 803 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 651 KiB

After

Width:  |  Height:  |  Size: 651 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 650 KiB

After

Width:  |  Height:  |  Size: 650 KiB

View file

@ -42,7 +42,7 @@ const (
appendixIconRadius = 16
)
var multipleOffset = geo.NewVector(10, -10)
var multipleOffset = geo.NewVector(d2target.MULTIPLE_OFFSET, -d2target.MULTIPLE_OFFSET)
//go:embed tooltip.svg
var TooltipIcon string
@ -734,7 +734,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
var multipleTL *geo.Point
if targetShape.Multiple {
multipleTL = tl.AddVector(geo.NewVector(d2target.MULTIPLE_OFFSET, -d2target.MULTIPLE_OFFSET))
multipleTL = tl.AddVector(multipleOffset)
}
switch targetShape.Type {
@ -744,13 +744,13 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
fmt.Fprint(writer, out)
} else {
drawClass(writer, targetShape)
}
addAppendixItems(writer, targetShape)
fmt.Fprintf(writer, `</g>`)
fmt.Fprintf(writer, closingTag)
fmt.Fprint(writer, `</g>`)
fmt.Fprint(writer, closingTag)
return labelMask, nil
case d2target.ShapeSQLTable:
if sketchRunner != nil {
@ -758,13 +758,13 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
fmt.Fprint(writer, out)
} else {
drawTable(writer, targetShape)
}
addAppendixItems(writer, targetShape)
fmt.Fprintf(writer, `</g>`)
fmt.Fprintf(writer, closingTag)
fmt.Fprint(writer, `</g>`)
fmt.Fprint(writer, closingTag)
return labelMask, nil
case d2target.ShapeOval:
if targetShape.DoubleBorder {
@ -776,7 +776,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
fmt.Fprint(writer, out)
} else {
fmt.Fprint(writer, renderDoubleOval(tl, width, height, style))
}
@ -789,7 +789,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
fmt.Fprint(writer, out)
} else {
fmt.Fprint(writer, renderOval(tl, width, height, style))
}
@ -815,7 +815,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
fmt.Fprint(writer, out)
} else {
fmt.Fprintf(writer, `<rect x="%d" y="%d" width="%d" height="%d" style="%s" />`,
targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, style)
@ -832,7 +832,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
fmt.Fprint(writer, out)
} else {
fmt.Fprintf(writer, `<rect x="%d" y="%d" width="%d" height="%d" style="%s" />`,
targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, style)
@ -855,7 +855,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
fmt.Fprint(writer, out)
} else {
for _, pathData := range s.GetSVGPathData() {
fmt.Fprintf(writer, `<path d="%s" style="%s"/>`, pathData, style)
@ -864,7 +864,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
}
// Closes the class=shape
fmt.Fprintf(writer, `</g>`)
fmt.Fprint(writer, `</g>`)
if targetShape.Icon != nil && targetShape.Type != d2target.ShapeImage {
iconPosition := label.Position(targetShape.IconPosition)
@ -895,7 +895,10 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
} else {
box = s.GetInnerBox()
}
labelTL := labelPosition.GetPointOnBox(box, label.PADDING, float64(targetShape.LabelWidth), float64(targetShape.LabelHeight))
labelTL := labelPosition.GetPointOnBox(box, label.PADDING,
float64(targetShape.LabelWidth),
float64(targetShape.LabelHeight),
)
fontClass := "text"
if targetShape.Bold {
@ -932,7 +935,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
fmt.Fprintf(writer, `<rect class="shape" width="%d" height="%d" style="%s" />`,
targetShape.Width, targetShape.Height, containerStyle)
// Padding
fmt.Fprintf(writer, `<g transform="translate(6 6)">`)
fmt.Fprint(writer, `<g transform="translate(6 6)">`)
for index, tokens := range chroma.SplitTokensIntoLines(iterator.Tokens()) {
// TODO mono font looks better with 1.2 em (use px equivalent), but textmeasure needs to account for it. Not obvious how that should be done
@ -947,7 +950,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
}
fmt.Fprint(writer, "</text>")
}
fmt.Fprintf(writer, "</g></g>")
fmt.Fprint(writer, "</g></g>")
} else if targetShape.Type == d2target.ShapeText && targetShape.Language == "latex" {
render, err := d2latex.Render(targetShape.Label)
if err != nil {
@ -955,7 +958,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
}
fmt.Fprintf(writer, `<g transform="translate(%f %f)">`, box.TopLeft.X, box.TopLeft.Y)
fmt.Fprint(writer, render)
fmt.Fprintf(writer, "</g>")
fmt.Fprint(writer, "</g>")
} else if targetShape.Type == d2target.ShapeText && targetShape.Language != "" {
render, err := textmeasure.RenderMarkdown(targetShape.Label)
if err != nil {
@ -1000,7 +1003,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
addAppendixItems(writer, targetShape)
fmt.Fprintf(writer, closingTag)
fmt.Fprint(writer, closingTag)
return labelMask, nil
}
@ -1268,7 +1271,7 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
fmt.Fprintf(buf, `<style type="text/css">%s</style>`, mdCSS)
}
if sketchRunner != nil {
fmt.Fprintf(buf, d2sketch.DefineFillPattern())
fmt.Fprint(buf, d2sketch.DefineFillPattern())
}
// only define shadow filter if a shape uses it

View file

@ -9,6 +9,9 @@ import (
const (
PrefixPadding = 10
PrefixWidth = 20
CenterPadding = 50
// 10px of padding top and bottom so text doesn't look squished
VerticalPadding = 20
)
type Class struct {

View file

@ -37,6 +37,10 @@ type Diagram struct {
Shapes []Shape `json:"shapes"`
Connections []Connection `json:"connections"`
Layers []*Diagram `json:"layers,omitempty"`
Scenarios []*Diagram `json:"scenarios,omitempty"`
Steps []*Diagram `json:"steps,omitempty"`
}
func (diagram Diagram) HashID() (string, error) {
@ -547,19 +551,19 @@ func (s *Shape) GetIconSize(box *geo.Box) int {
if iconPosition == label.InsideMiddleCenter {
size = halfMinDimension
} else {
size = go2.IntMin(
size = go2.Min(
minDimension,
go2.IntMax(DEFAULT_ICON_SIZE, halfMinDimension),
go2.Max(DEFAULT_ICON_SIZE, halfMinDimension),
)
}
size = go2.IntMin(size, MAX_ICON_SIZE)
size = go2.Min(size, MAX_ICON_SIZE)
if !iconPosition.IsOutside() {
size = go2.IntMin(size,
go2.IntMin(
go2.IntMax(int(box.Width)-2*label.PADDING, 0),
go2.IntMax(int(box.Height)-2*label.PADDING, 0),
size = go2.Min(size,
go2.Min(
go2.Max(int(box.Width)-2*label.PADDING, 0),
go2.Max(int(box.Height)-2*label.PADDING, 0),
),
)
}

View file

@ -17,6 +17,6 @@ If a change results in test diffs, you can run this script to generate a visual
report with the old vs new renders.
```
go run ./e2etests/report/main.go
go run ./e2etests/report/main.go -delta
open ./e2etests/out/e2e_report.html
```

View file

@ -12,7 +12,7 @@ import (
"cdr.dev/slog"
tassert "github.com/stretchr/testify/assert"
trequire "github.com/stretchr/testify/require"
"oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/util-go/diff"
@ -101,18 +101,18 @@ func serde(t *testing.T, tc testCase, ruler *textmeasure.Ruler) {
g, err := d2compiler.Compile("", strings.NewReader(tc.script), &d2compiler.CompileOptions{
UTF16: false,
})
tassert.Nil(t, err)
trequire.Nil(t, err)
if len(g.Objects) > 0 {
err = g.SetDimensions(nil, ruler, nil)
tassert.Nil(t, err)
trequire.Nil(t, err)
d2near.WithoutConstantNears(ctx, g)
d2sequence.WithoutSequenceDiagrams(ctx, g)
}
b, err := d2graph.SerializeGraph(g)
tassert.Nil(t, err)
trequire.Nil(t, err)
var newG d2graph.Graph
err = d2graph.DeserializeGraph(b, &newG)
tassert.Nil(t, err)
trequire.Nil(t, err)
}
func run(t *testing.T, tc testCase) {
@ -124,9 +124,7 @@ func run(t *testing.T, tc testCase) {
var err error
if tc.mtexts == nil {
ruler, err = textmeasure.NewRuler()
if !tassert.Nil(t, err) {
return
}
trequire.Nil(t, err)
serde(t, tc, ruler)
}
@ -150,9 +148,7 @@ func run(t *testing.T, tc testCase) {
ThemeID: 0,
Layout: layout,
})
if !tassert.Nil(t, err) {
return
}
trequire.Nil(t, err)
if tc.assertions != nil {
t.Run("assertions", func(t *testing.T) {
@ -171,26 +167,19 @@ func run(t *testing.T, tc testCase) {
assert.Success(t, err)
err = ioutil.WriteFile(pathGotSVG, svgBytes, 0600)
assert.Success(t, err)
// if running from e2ereport.sh, we want to keep .got.svg on a failure
forReport := os.Getenv("E2E_REPORT") != ""
if !forReport {
defer os.Remove(pathGotSVG)
}
// Check that it's valid SVG
var xmlParsed interface{}
err = xml.Unmarshal(svgBytes, &xmlParsed)
assert.Success(t, err)
var err2 error
err = diff.TestdataJSON(filepath.Join(dataPath, "board"), diagram)
assert.Success(t, err)
if os.Getenv("SKIP_SVG_CHECK") == "" {
err = diff.Testdata(filepath.Join(dataPath, "sketch"), ".svg", svgBytes)
assert.Success(t, err)
}
if forReport {
os.Remove(pathGotSVG)
err2 = diff.Testdata(filepath.Join(dataPath, "sketch"), ".svg", svgBytes)
}
assert.Success(t, err)
assert.Success(t, err2)
}
}

View file

@ -1,7 +1,10 @@
package e2etests
import (
"math"
"testing"
"oss.terrastruct.com/d2/d2target"
)
func testRegression(t *testing.T) {
@ -446,6 +449,30 @@ b -> c
`,
},
{
name: "empty_class_height",
script: `
class1: class with rows {
shape: class
-num: int
-timeout: int
}
class2: class without rows {
shape: class
}
`,
assertions: func(t *testing.T, g *d2target.Diagram) {
if len(g.Shapes) != 2 {
t.Fatal("expected 2 shapes")
}
c1Height := float64(g.Shapes[0].Height)
c2Height := float64(g.Shapes[1].Height)
if math.Round(c1Height/2.) != c2Height {
t.Fatal("expected rowless class to be 1/2 height of class with 2 rows")
}
},
},
}
runa(t, tcs)

View file

@ -6,6 +6,7 @@ import (
"flag"
"fmt"
"io/ioutil"
stdlog "log"
"os"
"os/exec"
"path/filepath"
@ -38,6 +39,7 @@ func main() {
flag.BoolVar(&deltaFlag, "delta", false, "Generate the report only for cases that changed.")
flag.StringVar(&testSetFlag, "test-set", "", "Only run set of tests matching this string. e.g. regressions")
flag.StringVar(&testCaseFlag, "test-case", "", "Only run tests matching this string. e.g. all_shapes")
skipTests := flag.Bool("skip-tests", false, "Skip running tests first")
flag.BoolVar(&vFlag, "v", false, "verbose")
flag.Parse()
@ -52,18 +54,20 @@ func main() {
testDir = "./e2etests"
}
ctx := log.Stderr(context.Background())
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
cmd := exec.CommandContext(ctx, "go", "test", testDir, "-run", testMatchString, vString)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "FORCE_COLOR=1")
cmd.Env = append(cmd.Env, "DEBUG=1")
cmd.Env = append(cmd.Env, "TEST_MODE=on")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Debug(ctx, cmd.String())
_ = cmd.Run()
if !*skipTests {
ctx := log.Stderr(context.Background())
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
cmd := exec.CommandContext(ctx, "go", "test", testDir, "-run", testMatchString, vString)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "FORCE_COLOR=1")
cmd.Env = append(cmd.Env, "DEBUG=1")
cmd.Env = append(cmd.Env, "TEST_MODE=on")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Debug(ctx, cmd.String())
_ = cmd.Run()
}
var tests []TestItem
err := filepath.Walk(filepath.Join(testDir, "testdata"), func(path string, info os.FileInfo, err error) error {
@ -144,6 +148,13 @@ func main() {
}
path := os.Getenv("REPORT_OUTPUT")
if path == "" {
path = filepath.Join(testDir, "./out/e2e_report.html")
}
err = os.MkdirAll(filepath.Dir(path), 0755)
if err != nil {
stdlog.Fatal(err)
}
f, err := os.Create(path)
if err != nil {
panic(fmt.Errorf("error creating file `%s`. %v", path, err))

View file

@ -1,16 +1,26 @@
<html>
<title>E2E report</title>
<body>
<h1>Table of Contents</h1>
<ul>
{{range .Tests}}
<li><a href="#{{.Name}}">{{.Name}}</a></li>
{{end}}
</ul>
<div class="cases">
{{range .Tests}}
<div class="case">
<h1><a href="../{{.GotSVG}}">{{.Name}}</a></h1>
<div class="case" id="{{.Name}}">
<h1><a href="../../{{.GotSVG}}">{{.Name}}</a></h1>
{{ if .ExpSVG }}
<h2>Expected</h2>
<img src="../{{.ExpSVG}}" width="100%" />
<h2>Got</h2>
<h2 class="case-exp">Expected</h2>
{{ end }}
<img src="../{{.GotSVG}}" width="100%" />
<h2 class="case-got">Got</h2>
<div class="case-img-wrapper">
{{ if .ExpSVG }}
<img src="../../{{.ExpSVG}}" width="100%" />
{{ end }}
<img src="../../{{.GotSVG}}" width="100%" />
</div>
</div>
{{end}}
</div>
@ -20,17 +30,24 @@
flex-wrap: wrap;
}
.case {
align-items: center;
justify-content: center;
position: relative;
padding: 20px;
width: 100%;
}
.case svg {
width: 400px;
height: 400px;
.case-img-wrapper {
display: flex;
align-items: center;
}
.case pre {
font-size: 10pt;
width: 400px;
.case img {
width: 600px;
}
.case-got {
position: absolute;
left: 600px;
}
.case h2 {
margin: 0;
display: inline;
}
</style>
</body>

View file

@ -79,23 +79,23 @@ callout -> stored_data -> person
diamond -> oval -> circle
hexagon -> cloud
rectangle.multiple: true
square.multiple: true
page.multiple: true
parallelogram.multiple: true
document.multiple: true
cylinder.multiple: true
queue.multiple: true
package.multiple: true
step.multiple: true
callout.multiple: true
stored_data.multiple: true
person.multiple: true
diamond.multiple: true
oval.multiple: true
circle.multiple: true
hexagon.multiple: true
cloud.multiple: true
rectangle.style.multiple: true
square.style.multiple: true
page.style.multiple: true
parallelogram.style.multiple: true
document.style.multiple: true
cylinder.style.multiple: true
queue.style.multiple: true
package.style.multiple: true
step.style.multiple: true
callout.style.multiple: true
stored_data.style.multiple: true
person.style.multiple: true
diamond.style.multiple: true
oval.style.multiple: true
circle.style.multiple: true
hexagon.style.multiple: true
cloud.style.multiple: true
`,
},
{
@ -126,23 +126,23 @@ callout -> stored_data -> person
diamond -> oval -> circle
hexagon -> cloud
rectangle.shadow: true
square.shadow: true
page.shadow: true
parallelogram.shadow: true
document.shadow: true
cylinder.shadow: true
queue.shadow: true
package.shadow: true
step.shadow: true
callout.shadow: true
stored_data.shadow: true
person.shadow: true
diamond.shadow: true
oval.shadow: true
circle.shadow: true
hexagon.shadow: true
cloud.shadow: true
rectangle.style.shadow: true
square.style.shadow: true
page.style.shadow: true
parallelogram.style.shadow: true
document.style.shadow: true
cylinder.style.shadow: true
queue.style.shadow: true
package.style.shadow: true
step.style.shadow: true
callout.style.shadow: true
stored_data.style.shadow: true
person.style.shadow: true
diamond.style.shadow: true
oval.style.shadow: true
circle.style.shadow: true
hexagon.style.shadow: true
cloud.style.shadow: true
`,
},
{
@ -153,8 +153,8 @@ square: {shape: "square"}
rectangle -> square
rectangle.3d: true
square.3d: true
rectangle.style.3d: true
square.style.3d: true
`,
},
{
@ -1109,17 +1109,17 @@ scorer.t -> itemOutcome.t3: setFeedback(missingConcepts)`,
script: `shape: sequence_diagram
scorer: {
stroke: red
stroke-width: 5
style.stroke: red
style.stroke-width: 5
}
scorer.abc: {
fill: yellow
stroke-width: 7
style.fill: yellow
style.stroke-width: 7
}
scorer -> itemResponse.a: {
stroke-width: 10
style.stroke-width: 10
}
itemResponse.a -> item.a.b
item.a.b -> essayRubric.a.b.c
@ -1877,6 +1877,97 @@ a.sp1 -> a.sp2: redirect
a.sp2 -> b: bar
`,
},
{
name: "people",
script: `
a.shape: person
b.shape: person
c.shape: person
d.shape: person
e.shape: person
f.shape: person
g.shape: person
a: -
b: --
c: ----
d: --------
e: ----------------
f: --------------------------------
g: ----------------------------------------------------------------
1.shape: person
2.shape: person
3.shape: person
4.shape: person
5.shape: person
1.width: 16
2.width: 64
3.width: 128
4.width: 512
# entering both width and height overrides aspect ratio limit
5.height: 256
5.width: 32
`,
},
{
name: "complex-layers",
script: `
desc: Multi-layer diagram of a home.
window: {
style.double-border: true
}
roof
garage
layers: {
window: {
blinds
glass
}
roof: {
shingles
starlink
utility hookup
}
garage: {
tools
vehicles
}
repair: {
desc: How to repair a home.
steps: {
1: {
find contractors: {
craigslist
facebook
}
}
2: {
find contractors -> solicit quotes
}
3: {
obtain quotes -> negotiate
}
4: {
negotiate -> book the best bid
}
}
}
}
scenarios: {
storm: {
water
rain
thunder
}
}`,
},
}
runa(t, tcs)

View file

@ -10,7 +10,7 @@
"y": 0
},
"width": 112,
"height": 12,
"height": 44,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="316" height="216" viewBox="-102 -102 316 216"><style type="text/css">
width="316" height="248" viewBox="-102 -102 316 248"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,7 +39,7 @@ width="316" height="216" viewBox="-102 -102 316 216"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="a"><g class="shape" ><rect class="shape" x="0" y="0" width="112" height="12" style="fill:#FFFFFF;stroke:#0A0F25;stroke-width:2;"/><rect class="class_header" x="0.000000" y="0.000000" width="112.000000" height="12.000000" fill="#0A0F25" /><line x1="0.000000" y1="12.000000" x2="112.000000" y2="12.000000" style="stroke-width:1;stroke:#0A0F25" /></g></g><mask id="3176154718" maskUnits="userSpaceOnUse" x="-100" y="-100" width="316" height="216">
<rect x="-100" y="-100" width="316" height="216" fill="white"></rect>
]]></script><g id="a"><g class="shape" ><rect class="shape" x="0" y="0" width="112" height="44" style="fill:#FFFFFF;stroke:#0A0F25;stroke-width:2;"/><rect class="class_header" x="0.000000" y="0.000000" width="112.000000" height="44.000000" fill="#0A0F25" /><line x1="0.000000" y1="44.000000" x2="112.000000" y2="44.000000" style="stroke-width:1;stroke:#0A0F25" /></g></g><mask id="2019199647" maskUnits="userSpaceOnUse" x="-100" y="-100" width="316" height="248">
<rect x="-100" y="-100" width="316" height="248" fill="white"></rect>
</mask><style type="text/css"><![CDATA[]]></style></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -4,7 +4,7 @@
"shapes": [
{
"id": "a",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0

View file

@ -39,7 +39,7 @@ width="304" height="304" viewBox="-102 -102 304 304"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="a"><g class="shape" ><rect x="0" y="0" width="100" height="100" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g></g><mask id="3624597608" maskUnits="userSpaceOnUse" x="-100" y="-100" width="304" height="304">
]]></script><g id="a"><g class="shape" ><rect x="0" y="0" width="100" height="100" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g></g><mask id="4175712569" maskUnits="userSpaceOnUse" x="-100" y="-100" width="304" height="304">
<rect x="-100" y="-100" width="304" height="304" fill="white"></rect>
</mask><style type="text/css"><![CDATA[]]></style></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -37,8 +37,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 239,
"labelHeight": 150,
"labelWidth": 234,
"labelHeight": 145,
"zIndex": 0,
"level": 1
},
@ -77,8 +77,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 118,
"labelWidth": 155,
"labelHeight": 113,
"zIndex": 0,
"level": 1
},
@ -117,8 +117,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 118,
"labelWidth": 155,
"labelHeight": 113,
"zIndex": 0,
"level": 1
}

View file

@ -56,7 +56,7 @@ width="883" height="354" viewBox="-102 -102 883 354"><style type="text/css">
</text><text class="text-mono" x="0" y="3.000000em" xml:space="preserve">
</text><text class="text-mono" x="0" y="4.000000em" xml:space="preserve">&#160;&#160;<tspan fill="#0086b3">print</tspan>&#160;<tspan fill="#dd1144"></tspan><tspan fill="#dd1144">&quot;</tspan><tspan fill="#dd1144">world</tspan><tspan fill="#dd1144">&quot;</tspan>
</text><text class="text-mono" x="0" y="5.000000em" xml:space="preserve">
</text></g></g></g><mask id="2229987818" maskUnits="userSpaceOnUse" x="-100" y="-100" width="883" height="354">
</text></g></g></g><mask id="2314789821" maskUnits="userSpaceOnUse" x="-100" y="-100" width="883" height="354">
<rect x="-100" y="-100" width="883" height="354" fill="white"></rect>
</mask><style type="text/css"><![CDATA[

Before

Width:  |  Height:  |  Size: 350 KiB

After

Width:  |  Height:  |  Size: 350 KiB

View file

@ -37,8 +37,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 239,
"labelHeight": 150,
"labelWidth": 234,
"labelHeight": 145,
"zIndex": 0,
"level": 1
},
@ -77,8 +77,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 118,
"labelWidth": 155,
"labelHeight": 113,
"zIndex": 0,
"level": 1
},
@ -117,8 +117,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 118,
"labelWidth": 155,
"labelHeight": 113,
"zIndex": 0,
"level": 1
}

View file

@ -56,7 +56,7 @@ width="803" height="354" viewBox="-90 -90 803 354"><style type="text/css">
</text><text class="text-mono" x="0" y="3.000000em" xml:space="preserve">
</text><text class="text-mono" x="0" y="4.000000em" xml:space="preserve">&#160;&#160;<tspan fill="#0086b3">print</tspan>&#160;<tspan fill="#dd1144"></tspan><tspan fill="#dd1144">&quot;</tspan><tspan fill="#dd1144">world</tspan><tspan fill="#dd1144">&quot;</tspan>
</text><text class="text-mono" x="0" y="5.000000em" xml:space="preserve">
</text></g></g></g><mask id="3995090615" maskUnits="userSpaceOnUse" x="-100" y="-100" width="803" height="354">
</text></g></g></g><mask id="2399438644" maskUnits="userSpaceOnUse" x="-100" y="-100" width="803" height="354">
<rect x="-100" y="-100" width="803" height="354" fill="white"></rect>
</mask><style type="text/css"><![CDATA[

Before

Width:  |  Height:  |  Size: 350 KiB

After

Width:  |  Height:  |  Size: 350 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "a",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 571,
"height": 648,
"width": 425,
"height": 528,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,103 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 17,
"labelHeight": 41,
"labelWidth": 12,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "a.c",
"type": "",
"pos": {
"x": 40,
"y": 359
},
"width": 478,
"height": 235,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "white",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 24,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 15,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.c.d",
"type": "",
"pos": {
"x": 236,
"y": 413
},
"width": 114,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 14,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "a.b",
"type": "",
"type": "rectangle",
"pos": {
"x": 64,
"x": 94,
"y": 55
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +78,62 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.1",
"type": "",
"id": "a.c",
"type": "rectangle",
"pos": {
"x": 237,
"x": 40,
"y": 299
},
"width": 345,
"height": 175,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "white",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 24,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 10,
"labelHeight": 31,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.1",
"type": "rectangle",
"pos": {
"x": 207,
"y": 55
},
"width": 112,
"height": 126,
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 12,
"labelHeight": 26,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.2",
"type": "",
"type": "rectangle",
"pos": {
"x": 409,
"x": 319,
"y": 55
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,11 +201,52 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.c.d",
"type": "rectangle",
"pos": {
"x": 206,
"y": 353
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 9,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
}
],
"connections": [
@ -277,19 +277,19 @@
"route": [
{
"x": 120,
"y": 181.5
"y": 121.5
},
{
"x": 120,
"y": 251.9
"y": 191.9
},
{
"x": 120,
"y": 287.5
"y": 227.5
},
{
"x": 120,
"y": 359.5
"y": 299.5
}
],
"isCurve": true,
@ -324,20 +324,20 @@
"labelPercentage": 0,
"route": [
{
"x": 292.5,
"y": 181.5
"x": 232.5,
"y": 121.5
},
{
"x": 292.5,
"y": 251.9
"x": 232.5,
"y": 191.9
},
{
"x": 292.5,
"y": 287.5
"x": 232.5,
"y": 227.5
},
{
"x": 292.5,
"y": 359.5
"x": 232.5,
"y": 299.5
}
],
"isCurve": true,
@ -372,20 +372,20 @@
"labelPercentage": 0,
"route": [
{
"x": 465,
"y": 181.5
"x": 345,
"y": 121.5
},
{
"x": 465,
"y": 251.9
"x": 345,
"y": 191.9
},
{
"x": 465,
"y": 287.5
"x": 345,
"y": 227.5
},
{
"x": 465,
"y": 359.5
"x": 345,
"y": 299.5
}
],
"isCurve": true,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="775" height="852" viewBox="-102 -102 775 852"><style type="text/css">
width="629" height="732" viewBox="-102 -102 629 732"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,9 +39,9 @@ width="775" height="852" viewBox="-102 -102 775 852"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="a"><g class="shape" ><rect x="0" y="0" width="571" height="648" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="285.500000" y="33.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">a</text></g><g id="a.c"><g class="shape" ><rect x="40" y="359" width="478" height="235" style="fill:#EDF0FD;stroke:white;stroke-width:2;" /></g><text class="text" x="279.000000" y="388.000000" style="text-anchor:middle;font-size:24px;fill:#0A0F25">c</text></g><g id="a.b"><g class="shape" ><rect x="64" y="55" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="120.500000" y="121.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="a.1"><g class="shape" ><rect x="237" y="55" width="112" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="293.000000" y="121.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">1</text></g><g id="a.2"><g class="shape" ><rect x="409" y="55" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="465.500000" y="121.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">2</text></g><g id="a.c.d"><g class="shape" ><rect x="236" y="413" width="114" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="293.000000" y="479.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">d</text></g><g id="a.(b -&gt; c)[0]"><marker id="mk-1065319532" markerWidth="24.200000" markerHeight="18.000000" refX="20.800000" refY="9.000000" viewBox="0.000000 0.000000 24.200000 18.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="white" stroke="red" stroke-width="2" points="0.000000,9.000000 11.000000,2.250000 22.000000,9.000000 11.000000,16.200000" /> </marker><path d="M 120.000000 183.500000 C 120.000000 251.900000 120.000000 287.500000 120.000000 355.500000" class="connection" style="fill:none;stroke:red;stroke-width:2;" marker-end="url(#mk-1065319532)" mask="url(#1474862432)"/><text class="text-italic" x="120.000000" y="252.000000" style="text-anchor:middle;font-size:16px;fill:red"><tspan x="120.000000" dy="0.000000">line 1</tspan><tspan x="120.000000" dy="17.250000">line 2</tspan><tspan x="120.000000" dy="17.250000">line 3</tspan><tspan x="120.000000" dy="17.250000">line 4</tspan></text></g><g id="a.(1 -&gt; c)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 292.500000 183.500000 C 292.500000 251.900000 292.500000 287.500000 292.500000 355.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1474862432)"/></g><g id="a.(2 &lt;-&gt; c)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 465.000000 185.500000 C 465.000000 251.900000 465.000000 287.500000 465.000000 355.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#1474862432)"/></g><mask id="1474862432" maskUnits="userSpaceOnUse" x="-100" y="-100" width="775" height="852">
<rect x="-100" y="-100" width="775" height="852" fill="white"></rect>
<rect x="102.000000" y="236.000000" width="36" height="69" fill="black"></rect>
]]></script><g id="a"><g class="shape" ><rect x="0" y="0" width="425" height="528" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="212.500000" y="33.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">a</text></g><g id="a.b"><g class="shape" ><rect x="94" y="55" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="120.500000" y="93.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="a.c"><g class="shape" ><rect x="40" y="299" width="345" height="175" style="fill:#EDF0FD;stroke:white;stroke-width:2;" /></g><text class="text" x="212.500000" y="328.000000" style="text-anchor:middle;font-size:24px;fill:#0A0F25">c</text></g><g id="a.1"><g class="shape" ><rect x="207" y="55" width="52" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="233.000000" y="93.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">1</text></g><g id="a.2"><g class="shape" ><rect x="319" y="55" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="345.500000" y="93.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">2</text></g><g id="a.c.d"><g class="shape" ><rect x="206" y="353" width="54" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="233.000000" y="391.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">d</text></g><g id="a.(b -&gt; c)[0]"><marker id="mk-1065319532" markerWidth="24.200000" markerHeight="18.000000" refX="20.800000" refY="9.000000" viewBox="0.000000 0.000000 24.200000 18.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="white" stroke="red" stroke-width="2" points="0.000000,9.000000 11.000000,2.250000 22.000000,9.000000 11.000000,16.200000" /> </marker><path d="M 120.000000 123.500000 C 120.000000 191.900000 120.000000 227.500000 120.000000 295.500000" class="connection" style="fill:none;stroke:red;stroke-width:2;" marker-end="url(#mk-1065319532)" mask="url(#89896559)"/><text class="text-italic" x="120.000000" y="192.000000" style="text-anchor:middle;font-size:16px;fill:red"><tspan x="120.000000" dy="0.000000">line 1</tspan><tspan x="120.000000" dy="17.250000">line 2</tspan><tspan x="120.000000" dy="17.250000">line 3</tspan><tspan x="120.000000" dy="17.250000">line 4</tspan></text></g><g id="a.(1 -&gt; c)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 232.500000 123.500000 C 232.500000 191.900000 232.500000 227.500000 232.500000 295.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#89896559)"/></g><g id="a.(2 &lt;-&gt; c)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 345.000000 125.500000 C 345.000000 191.900000 345.000000 227.500000 345.000000 295.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#89896559)"/></g><mask id="89896559" maskUnits="userSpaceOnUse" x="-100" y="-100" width="629" height="732">
<rect x="-100" y="-100" width="629" height="732" fill="white"></rect>
<rect x="102.000000" y="176.000000" width="36" height="69" fill="black"></rect>
</mask><style type="text/css"><![CDATA[
.text {
font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 794 KiB

After

Width:  |  Height:  |  Size: 794 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "a",
"type": "",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 490,
"height": 878,
"width": 354,
"height": 701,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,103 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 17,
"labelHeight": 41,
"labelWidth": 12,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "a.c",
"type": "",
"pos": {
"x": 106,
"y": 539
},
"width": 264,
"height": 276,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "white",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 24,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 15,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.c.d",
"type": "",
"pos": {
"x": 181,
"y": 614
},
"width": 114,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 14,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "a.b",
"type": "",
"type": "rectangle",
"pos": {
"x": 87,
"x": 97,
"y": 87
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +78,62 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.1",
"type": "",
"id": "a.c",
"type": "rectangle",
"pos": {
"x": 182,
"y": 313
"x": 87,
"y": 422
},
"width": 112,
"height": 126,
"width": 204,
"height": 216,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "white",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 24,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 10,
"labelHeight": 31,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.1",
"type": "rectangle",
"pos": {
"x": 163,
"y": 256
},
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 12,
"labelHeight": 26,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.2",
"type": "",
"type": "rectangle",
"pos": {
"x": 314,
"y": 313
"x": 235,
"y": 256
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,11 +201,52 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.c.d",
"type": "rectangle",
"pos": {
"x": 162,
"y": 497
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 9,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
}
],
"connections": [
@ -276,20 +276,20 @@
"labelPercentage": 0,
"route": [
{
"x": 143.5,
"y": 213
"x": 124,
"y": 153
},
{
"x": 143.5,
"y": 489
"x": 124,
"y": 372
},
{
"x": 172.5,
"y": 489
"x": 138,
"y": 372
},
{
"x": 172.5,
"y": 539
"x": 138,
"y": 422
}
],
"animated": false,
@ -323,12 +323,12 @@
"labelPercentage": 0,
"route": [
{
"x": 238.5,
"y": 439
"x": 189,
"y": 322
},
{
"x": 238.5,
"y": 539
"x": 189,
"y": 422
}
],
"animated": false,
@ -362,20 +362,20 @@
"labelPercentage": 0,
"route": [
{
"x": 371,
"y": 439
"x": 261.5,
"y": 322
},
{
"x": 371,
"y": 489
"x": 261.5,
"y": 372
},
{
"x": 304.5,
"y": 489
"x": 240,
"y": 372
},
{
"x": 304.5,
"y": 539
"x": 240,
"y": 422
}
],
"animated": false,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="694" height="1082" viewBox="-90 -90 694 1082"><style type="text/css">
width="558" height="905" viewBox="-90 -90 558 905"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,9 +39,9 @@ width="694" height="1082" viewBox="-90 -90 694 1082"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="a"><g class="shape" ><rect x="12" y="12" width="490" height="878" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="257.000000" y="45.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">a</text></g><g id="a.c"><g class="shape" ><rect x="106" y="539" width="264" height="276" style="fill:#EDF0FD;stroke:white;stroke-width:2;" /></g><text class="text" x="238.000000" y="568.000000" style="text-anchor:middle;font-size:24px;fill:#0A0F25">c</text></g><g id="a.b"><g class="shape" ><rect x="87" y="87" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="143.500000" y="153.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="a.1"><g class="shape" ><rect x="182" y="313" width="112" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="238.000000" y="379.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">1</text></g><g id="a.2"><g class="shape" ><rect x="314" y="313" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="370.500000" y="379.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">2</text></g><g id="a.c.d"><g class="shape" ><rect x="181" y="614" width="114" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="238.000000" y="680.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">d</text></g><g id="a.(b -&gt; c)[0]"><marker id="mk-1065319532" markerWidth="24.200000" markerHeight="18.000000" refX="20.800000" refY="9.000000" viewBox="0.000000 0.000000 24.200000 18.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="white" stroke="red" stroke-width="2" points="0.000000,9.000000 11.000000,2.250000 22.000000,9.000000 11.000000,16.200000" /> </marker><path d="M 143.500000 215.000000 L 143.500000 479.000000 S 143.500000 489.000000 153.500000 489.000000 L 162.500000 489.000000 S 172.500000 489.000000 172.500000 499.000000 L 172.500000 535.000000" class="connection" style="fill:none;stroke:red;stroke-width:2;" marker-end="url(#mk-1065319532)" mask="url(#3390014606)"/><text class="text-italic" x="144.000000" y="372.000000" style="text-anchor:middle;font-size:16px;fill:red"><tspan x="144.000000" dy="0.000000">line 1</tspan><tspan x="144.000000" dy="17.250000">line 2</tspan><tspan x="144.000000" dy="17.250000">line 3</tspan><tspan x="144.000000" dy="17.250000">line 4</tspan></text></g><g id="a.(1 -&gt; c)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 238.500000 441.000000 L 238.500000 535.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#3390014606)"/></g><g id="a.(2 &lt;-&gt; c)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 371.000000 443.000000 L 371.000000 479.000000 S 371.000000 489.000000 361.000000 489.000000 L 314.500000 489.000000 S 304.500000 489.000000 304.500000 499.000000 L 304.500000 535.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#3390014606)"/></g><mask id="3390014606" maskUnits="userSpaceOnUse" x="-100" y="-100" width="694" height="1082">
<rect x="-100" y="-100" width="694" height="1082" fill="white"></rect>
<rect x="126.000000" y="356.000000" width="36" height="69" fill="black"></rect>
]]></script><g id="a"><g class="shape" ><rect x="12" y="12" width="354" height="701" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="189.000000" y="45.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">a</text></g><g id="a.b"><g class="shape" ><rect x="97" y="87" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="123.500000" y="125.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="a.c"><g class="shape" ><rect x="87" y="422" width="204" height="216" style="fill:#EDF0FD;stroke:white;stroke-width:2;" /></g><text class="text" x="189.000000" y="451.000000" style="text-anchor:middle;font-size:24px;fill:#0A0F25">c</text></g><g id="a.1"><g class="shape" ><rect x="163" y="256" width="52" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="189.000000" y="294.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">1</text></g><g id="a.2"><g class="shape" ><rect x="235" y="256" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="261.500000" y="294.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">2</text></g><g id="a.c.d"><g class="shape" ><rect x="162" y="497" width="54" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="189.000000" y="535.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">d</text></g><g id="a.(b -&gt; c)[0]"><marker id="mk-1065319532" markerWidth="24.200000" markerHeight="18.000000" refX="20.800000" refY="9.000000" viewBox="0.000000 0.000000 24.200000 18.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="white" stroke="red" stroke-width="2" points="0.000000,9.000000 11.000000,2.250000 22.000000,9.000000 11.000000,16.200000" /> </marker><path d="M 124.000000 155.000000 L 124.000000 365.000000 C 124.000000 379.000000 138.000000 365.000000 138.000000 379.000000 L 138.000000 418.000000" class="connection" style="fill:none;stroke:red;stroke-width:2;" marker-end="url(#mk-1065319532)" mask="url(#731079584)"/><text class="text-italic" x="124.000000" y="276.000000" style="text-anchor:middle;font-size:16px;fill:red"><tspan x="124.000000" dy="0.000000">line 1</tspan><tspan x="124.000000" dy="17.250000">line 2</tspan><tspan x="124.000000" dy="17.250000">line 3</tspan><tspan x="124.000000" dy="17.250000">line 4</tspan></text></g><g id="a.(1 -&gt; c)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 189.000000 324.000000 L 189.000000 418.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#731079584)"/></g><g id="a.(2 &lt;-&gt; c)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 261.500000 326.000000 L 261.500000 362.000000 S 261.500000 372.000000 251.500000 372.000000 L 250.000000 372.000000 S 240.000000 372.000000 240.000000 382.000000 L 240.000000 418.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#731079584)"/></g><mask id="731079584" maskUnits="userSpaceOnUse" x="-100" y="-100" width="558" height="905">
<rect x="-100" y="-100" width="558" height="905" fill="white"></rect>
<rect x="106.000000" y="260.000000" width="36" height="69" fill="black"></rect>
</mask><style type="text/css"><![CDATA[
.text {
font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 794 KiB

After

Width:  |  Height:  |  Size: 794 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "build_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 2628,
"height": 237,
"width": 2328,
"height": 177,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 226,
"labelHeight": 41,
"labelWidth": 221,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "build_workflow.push",
"type": "",
"type": "rectangle",
"pos": {
"x": 105,
"y": 50
},
"width": 330,
"height": 137,
"width": 270,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 230,
"labelHeight": 37,
"labelWidth": 225,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 698,
"x": 638,
"y": 50
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,21 +119,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.S3",
"type": "",
"type": "rectangle",
"pos": {
"x": 1314,
"x": 1194,
"y": 50
},
"width": 131,
"height": 137,
"width": 71,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 31,
"labelHeight": 37,
"labelWidth": 26,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.Terraform",
"type": "",
"type": "rectangle",
"pos": {
"x": 1773,
"x": 1593,
"y": 50
},
"width": 218,
"height": 137,
"width": 158,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +201,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 118,
"labelHeight": 37,
"labelWidth": 113,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 2369,
"x": 2129,
"y": 50
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,8 +242,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -276,20 +276,20 @@
"labelPercentage": 0,
"route": [
{
"x": 435.5,
"y": 118.5
"x": 375.5,
"y": 88.5
},
{
"x": 539.9,
"y": 118.5
"x": 479.9,
"y": 88.5
},
{
"x": 592.3,
"y": 118.5
"x": 532.3,
"y": 88.5
},
{
"x": 697.5,
"y": 118.5
"x": 637.5,
"y": 88.5
}
],
"isCurve": true,
@ -324,20 +324,20 @@
"labelPercentage": 0,
"route": [
{
"x": 966.5,
"y": 118.5
"x": 846.5,
"y": 88.5
},
{
"x": 1105.3,
"y": 118.5
"x": 985.3,
"y": 88.5
},
{
"x": 1174.7,
"y": 118.5
"x": 1054.7,
"y": 88.5
},
{
"x": 1313.5,
"y": 118.5
"x": 1193.5,
"y": 88.5
}
],
"isCurve": true,
@ -372,20 +372,20 @@
"labelPercentage": 0,
"route": [
{
"x": 1445.5,
"y": 118.5
"x": 1265.5,
"y": 88.5
},
{
"x": 1575.9,
"y": 118.5
"x": 1395.9,
"y": 88.5
},
{
"x": 1641.3,
"y": 118.5
"x": 1461.3,
"y": 88.5
},
{
"x": 1772.5,
"y": 118.5
"x": 1592.5,
"y": 88.5
}
],
"isCurve": true,
@ -420,20 +420,20 @@
"labelPercentage": 0,
"route": [
{
"x": 1991.5,
"y": 118.5
"x": 1751.5,
"y": 88.5
},
{
"x": 2141.9,
"y": 118.5
"x": 1901.9,
"y": 88.5
},
{
"x": 2217.3,
"y": 118.5
"x": 1977.3,
"y": 88.5
},
{
"x": 2368.5,
"y": 118.5
"x": 2128.5,
"y": 88.5
}
],
"isCurve": true,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="2832" height="441" viewBox="-102 -102 2832 441"><style type="text/css">
width="2532" height="381" viewBox="-102 -102 2532 381"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,12 +39,12 @@ width="2832" height="441" viewBox="-102 -102 2832 441"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="build_workflow"><g class="shape" ><rect x="0" y="0" width="2628" height="237" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="1314.000000" y="33.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">lambda-build.yaml</text></g><g id="build_workflow.push"><g class="shape" ><rect x="105" y="50" width="330" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="270.000000" y="125.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Push to main branch</text></g><g id="build_workflow.GHA"><g class="shape" ><rect x="698" y="50" width="269" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="832.500000" y="125.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">GitHub Actions</text></g><g id="build_workflow.S3"><g class="shape" ><rect x="1314" y="50" width="131" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1379.500000" y="125.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">S3</text></g><g id="build_workflow.Terraform"><g class="shape" ><rect x="1773" y="50" width="218" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1882.000000" y="125.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Terraform</text></g><g id="build_workflow.AWS"><g class="shape" ><rect x="2369" y="50" width="155" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="2446.500000" y="125.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">AWS</text></g><g id="build_workflow.(push -&gt; GHA)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 437.500000 118.500000 C 539.900000 118.500000 592.300000 118.500000 693.500000 118.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#351638657)"/><text class="text-italic" x="567.000000" y="124.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Triggers</text></g><g id="build_workflow.(GHA -&gt; S3)[0]"><path d="M 968.500000 118.500000 C 1105.300000 118.500000 1174.700000 118.500000 1309.500000 118.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#351638657)"/><text class="text-italic" x="1140.000000" y="124.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Builds zip &amp; pushes it</text></g><g id="build_workflow.(S3 &lt;-&gt; Terraform)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 1449.500000 118.500000 C 1575.900000 118.500000 1641.300000 118.500000 1768.500000 118.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#351638657)"/><text class="text-italic" x="1609.500000" y="124.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Pulls zip to deploy</text></g><g id="build_workflow.(Terraform -&gt; AWS)[0]"><path d="M 1993.500000 118.500000 C 2141.900000 118.500000 2217.300000 118.500000 2364.500000 118.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#351638657)"/><text class="text-italic" x="2180.500000" y="124.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Changes the live lambdas</text></g><mask id="351638657" maskUnits="userSpaceOnUse" x="-100" y="-100" width="2832" height="441">
<rect x="-100" y="-100" width="2832" height="441" fill="white"></rect>
<rect x="540.000000" y="108.000000" width="54" height="21" fill="black"></rect>
<rect x="1071.000000" y="108.000000" width="138" height="21" fill="black"></rect>
<rect x="1550.000000" y="108.000000" width="119" height="21" fill="black"></rect>
<rect x="2096.000000" y="108.000000" width="169" height="21" fill="black"></rect>
]]></script><g id="build_workflow"><g class="shape" ><rect x="0" y="0" width="2328" height="177" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="1164.000000" y="33.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">lambda-build.yaml</text></g><g id="build_workflow.push"><g class="shape" ><rect x="105" y="50" width="270" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="240.000000" y="97.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Push to main branch</text></g><g id="build_workflow.GHA"><g class="shape" ><rect x="638" y="50" width="209" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="742.500000" y="97.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">GitHub Actions</text></g><g id="build_workflow.S3"><g class="shape" ><rect x="1194" y="50" width="71" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1229.500000" y="97.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">S3</text></g><g id="build_workflow.Terraform"><g class="shape" ><rect x="1593" y="50" width="158" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1672.000000" y="97.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Terraform</text></g><g id="build_workflow.AWS"><g class="shape" ><rect x="2129" y="50" width="95" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="2176.500000" y="97.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">AWS</text></g><g id="build_workflow.(push -&gt; GHA)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 377.500000 88.500000 C 479.900000 88.500000 532.300000 88.500000 633.500000 88.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2796260647)"/><text class="text-italic" x="507.000000" y="94.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Triggers</text></g><g id="build_workflow.(GHA -&gt; S3)[0]"><path d="M 848.500000 88.500000 C 985.300000 88.500000 1054.700000 88.500000 1189.500000 88.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2796260647)"/><text class="text-italic" x="1020.000000" y="94.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Builds zip &amp; pushes it</text></g><g id="build_workflow.(S3 &lt;-&gt; Terraform)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 1269.500000 88.500000 C 1395.900000 88.500000 1461.300000 88.500000 1588.500000 88.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#2796260647)"/><text class="text-italic" x="1429.500000" y="94.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Pulls zip to deploy</text></g><g id="build_workflow.(Terraform -&gt; AWS)[0]"><path d="M 1753.500000 88.500000 C 1901.900000 88.500000 1977.300000 88.500000 2124.500000 88.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2796260647)"/><text class="text-italic" x="1940.500000" y="94.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Changes the live lambdas</text></g><mask id="2796260647" maskUnits="userSpaceOnUse" x="-100" y="-100" width="2532" height="381">
<rect x="-100" y="-100" width="2532" height="381" fill="white"></rect>
<rect x="480.000000" y="78.000000" width="54" height="21" fill="black"></rect>
<rect x="951.000000" y="78.000000" width="138" height="21" fill="black"></rect>
<rect x="1370.000000" y="78.000000" width="119" height="21" fill="black"></rect>
<rect x="1856.000000" y="78.000000" width="169" height="21" fill="black"></rect>
</mask><style type="text/css"><![CDATA[
.text {
font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 795 KiB

After

Width:  |  Height:  |  Size: 795 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "build_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 2533,
"height": 287,
"width": 2233,
"height": 227,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 226,
"labelHeight": 41,
"labelWidth": 221,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "build_workflow.push",
"type": "",
"type": "rectangle",
"pos": {
"x": 87,
"y": 87
},
"width": 330,
"height": 137,
"width": 270,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 230,
"labelHeight": 37,
"labelWidth": 225,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 671,
"x": 611,
"y": 87
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,21 +119,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.S3",
"type": "",
"type": "rectangle",
"pos": {
"x": 1278,
"x": 1158,
"y": 87
},
"width": 131,
"height": 137,
"width": 71,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 31,
"labelHeight": 37,
"labelWidth": 26,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.Terraform",
"type": "",
"type": "rectangle",
"pos": {
"x": 1728,
"x": 1548,
"y": 87
},
"width": 218,
"height": 137,
"width": 158,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +201,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 118,
"labelHeight": 37,
"labelWidth": 113,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 2315,
"x": 2075,
"y": 87
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,8 +242,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -276,12 +276,12 @@
"labelPercentage": 0,
"route": [
{
"x": 417,
"y": 155.5
"x": 357,
"y": 125.5
},
{
"x": 671,
"y": 155.5
"x": 611,
"y": 125.5
}
],
"animated": false,
@ -315,12 +315,12 @@
"labelPercentage": 0,
"route": [
{
"x": 940,
"y": 155.5
"x": 820,
"y": 125.5
},
{
"x": 1278,
"y": 155.5
"x": 1158,
"y": 125.5
}
],
"animated": false,
@ -354,12 +354,12 @@
"labelPercentage": 0,
"route": [
{
"x": 1409,
"y": 155.5
"x": 1229,
"y": 125.5
},
{
"x": 1728,
"y": 155.5
"x": 1548,
"y": 125.5
}
],
"animated": false,
@ -393,12 +393,12 @@
"labelPercentage": 0,
"route": [
{
"x": 1946,
"y": 155.5
"x": 1706,
"y": 125.5
},
{
"x": 2315,
"y": 155.5
"x": 2075,
"y": 125.5
}
],
"animated": false,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="2737" height="491" viewBox="-90 -90 2737 491"><style type="text/css">
width="2437" height="431" viewBox="-90 -90 2437 431"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,12 +39,12 @@ width="2737" height="491" viewBox="-90 -90 2737 491"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="build_workflow"><g class="shape" ><rect x="12" y="12" width="2533" height="287" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="1278.500000" y="45.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">lambda-build.yaml</text></g><g id="build_workflow.push"><g class="shape" ><rect x="87" y="87" width="330" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="252.000000" y="162.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Push to main branch</text></g><g id="build_workflow.GHA"><g class="shape" ><rect x="671" y="87" width="269" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="805.500000" y="162.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">GitHub Actions</text></g><g id="build_workflow.S3"><g class="shape" ><rect x="1278" y="87" width="131" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1343.500000" y="162.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">S3</text></g><g id="build_workflow.Terraform"><g class="shape" ><rect x="1728" y="87" width="218" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1837.000000" y="162.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Terraform</text></g><g id="build_workflow.AWS"><g class="shape" ><rect x="2315" y="87" width="155" height="137" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="2392.500000" y="162.000000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">AWS</text></g><g id="build_workflow.(push -&gt; GHA)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 419.000000 155.500000 L 667.000000 155.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1057310123)"/><text class="text-italic" x="544.000000" y="161.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Triggers</text></g><g id="build_workflow.(GHA -&gt; S3)[0]"><path d="M 942.000000 155.500000 L 1274.000000 155.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1057310123)"/><text class="text-italic" x="1109.000000" y="161.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Builds zip &amp; pushes it</text></g><g id="build_workflow.(S3 &lt;-&gt; Terraform)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 1413.000000 155.500000 L 1724.000000 155.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#1057310123)"/><text class="text-italic" x="1568.500000" y="161.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Pulls zip to deploy</text></g><g id="build_workflow.(Terraform -&gt; AWS)[0]"><path d="M 1948.000000 155.500000 L 2311.000000 155.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1057310123)"/><text class="text-italic" x="2130.500000" y="161.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Changes the live lambdas</text></g><mask id="1057310123" maskUnits="userSpaceOnUse" x="-100" y="-100" width="2737" height="491">
<rect x="-100" y="-100" width="2737" height="491" fill="white"></rect>
<rect x="517.000000" y="145.000000" width="54" height="21" fill="black"></rect>
<rect x="1040.000000" y="145.000000" width="138" height="21" fill="black"></rect>
<rect x="1509.000000" y="145.000000" width="119" height="21" fill="black"></rect>
<rect x="2046.000000" y="145.000000" width="169" height="21" fill="black"></rect>
]]></script><g id="build_workflow"><g class="shape" ><rect x="12" y="12" width="2233" height="227" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="1128.500000" y="45.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">lambda-build.yaml</text></g><g id="build_workflow.push"><g class="shape" ><rect x="87" y="87" width="270" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="222.000000" y="134.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Push to main branch</text></g><g id="build_workflow.GHA"><g class="shape" ><rect x="611" y="87" width="209" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="715.500000" y="134.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">GitHub Actions</text></g><g id="build_workflow.S3"><g class="shape" ><rect x="1158" y="87" width="71" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1193.500000" y="134.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">S3</text></g><g id="build_workflow.Terraform"><g class="shape" ><rect x="1548" y="87" width="158" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1627.000000" y="134.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">Terraform</text></g><g id="build_workflow.AWS"><g class="shape" ><rect x="2075" y="87" width="95" height="77" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="2122.500000" y="134.500000" style="text-anchor:middle;font-size:25px;fill:#0A0F25">AWS</text></g><g id="build_workflow.(push -&gt; GHA)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 359.000000 125.500000 L 607.000000 125.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#483332612)"/><text class="text-italic" x="484.000000" y="131.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Triggers</text></g><g id="build_workflow.(GHA -&gt; S3)[0]"><path d="M 822.000000 125.500000 L 1154.000000 125.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#483332612)"/><text class="text-italic" x="989.000000" y="131.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Builds zip &amp; pushes it</text></g><g id="build_workflow.(S3 &lt;-&gt; Terraform)[0]"><marker id="mk-2510427236" markerWidth="10.000000" markerHeight="12.000000" refX="3.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="10.000000,0.000000 0.000000,6.000000 10.000000,12.000000" /> </marker><path d="M 1233.000000 125.500000 L 1544.000000 125.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-start="url(#mk-2510427236)" marker-end="url(#mk-3990223579)" mask="url(#483332612)"/><text class="text-italic" x="1388.500000" y="131.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Pulls zip to deploy</text></g><g id="build_workflow.(Terraform -&gt; AWS)[0]"><path d="M 1708.000000 125.500000 L 2071.000000 125.500000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#483332612)"/><text class="text-italic" x="1890.500000" y="131.000000" style="text-anchor:middle;font-size:16px;fill:#676C7E">Changes the live lambdas</text></g><mask id="483332612" maskUnits="userSpaceOnUse" x="-100" y="-100" width="2437" height="431">
<rect x="-100" y="-100" width="2437" height="431" fill="white"></rect>
<rect x="457.000000" y="115.000000" width="54" height="21" fill="black"></rect>
<rect x="920.000000" y="115.000000" width="138" height="21" fill="black"></rect>
<rect x="1329.000000" y="115.000000" width="119" height="21" fill="black"></rect>
<rect x="1806.000000" y="115.000000" width="169" height="21" fill="black"></rect>
</mask><style type="text/css"><![CDATA[
.text {
font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 795 KiB

After

Width:  |  Height:  |  Size: 795 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "\"ninety\\nnine\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 151,
"height": 142,
"width": 91,
"height": 82,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 51,
"labelHeight": 42,
"labelWidth": 46,
"labelHeight": 37,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "eighty\reight",
"type": "",
"type": "rectangle",
"pos": {
"x": 211,
"x": 151,
"y": 8
},
"width": 151,
"height": 126,
"width": 91,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 51,
"labelHeight": 26,
"labelWidth": 46,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "\"seventy\r\\nseven\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 422,
"x": 302,
"y": 0
},
"width": 162,
"height": 142,
"width": 102,
"height": 82,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,21 +119,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 62,
"labelHeight": 42,
"labelWidth": 57,
"labelHeight": 37,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "\"a\\\\yode\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 644,
"x": 464,
"y": 8
},
"width": 154,
"height": 126,
"width": 94,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 54,
"labelHeight": 26,
"labelWidth": 49,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "there",
"type": "",
"type": "rectangle",
"pos": {
"x": 864,
"y": 242
"x": 624,
"y": 182
},
"width": 143,
"height": 126,
"width": 83,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +201,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 43,
"labelHeight": 26,
"labelWidth": 38,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "'a\\\"ode'",
"type": "",
"type": "rectangle",
"pos": {
"x": 858,
"x": 618,
"y": 8
},
"width": 154,
"height": 126,
"width": 94,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,21 +242,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 54,
"labelHeight": 26,
"labelWidth": 49,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "\"a\\\\node\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 1072,
"x": 772,
"y": 8
},
"width": 155,
"height": 126,
"width": 95,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -283,8 +283,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 26,
"labelWidth": 50,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -317,20 +317,20 @@
"labelPercentage": 0,
"route": [
{
"x": 721,
"y": 134
"x": 511,
"y": 74
},
{
"x": 721,
"y": 180.4
"x": 511,
"y": 120.4
},
{
"x": 749.5,
"y": 207.04906542056074
"x": 533.5,
"y": 144.12662337662337
},
{
"x": 863.5,
"y": 267.24532710280374
"x": 623.5,
"y": 192.63311688311688
}
],
"isCurve": true,
@ -365,20 +365,20 @@
"labelPercentage": 0,
"route": [
{
"x": 935,
"y": 134
"x": 665,
"y": 74
},
{
"x": 935,
"y": 180.4
"x": 665,
"y": 120.4
},
{
"x": 935,
"y": 202
"x": 665,
"y": 142
},
{
"x": 935,
"y": 242
"x": 665,
"y": 182
}
],
"isCurve": true,
@ -413,20 +413,20 @@
"labelPercentage": 0,
"route": [
{
"x": 1149.5,
"y": 134
"x": 819.5,
"y": 74
},
{
"x": 1149.5,
"y": 180.4
"x": 819.5,
"y": 120.4
},
{
"x": 1120.9,
"y": 207
"x": 796.9,
"y": 144
},
{
"x": 1006.5,
"y": 267
"x": 706.5,
"y": 192
}
],
"isCurve": true,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="1431" height="572" viewBox="-102 -102 1431 572"><style type="text/css">
width="1071" height="452" viewBox="-102 -102 1071 452"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,8 +39,8 @@ width="1431" height="572" viewBox="-102 -102 1431 572"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="&#34;ninety\nnine&#34;"><g class="shape" ><rect x="0" y="0" width="151" height="142" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="75.500000" y="66.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="75.500000" dy="0.000000">ninety</tspan><tspan x="75.500000" dy="21.000000">nine</tspan></text></g><g id="eighty&#xD;eight"><g class="shape" ><rect x="211" y="8" width="151" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="286.500000" y="74.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">eighty&#xD;eight</text></g><g id="&#34;seventy&#xD;\nseven&#34;"><g class="shape" ><rect x="422" y="0" width="162" height="142" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="503.000000" y="66.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="503.000000" dy="0.000000">seventy&#xD;</tspan><tspan x="503.000000" dy="21.000000">seven</tspan></text></g><g id="&#34;a\\yode&#34;"><g class="shape" ><rect x="644" y="8" width="154" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="721.000000" y="74.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\yode</text></g><g id="there"><g class="shape" ><rect x="864" y="242" width="143" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="935.500000" y="308.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">there</text></g><g id="&#39;a\&#34;ode&#39;"><g class="shape" ><rect x="858" y="8" width="154" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="935.000000" y="74.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\&#34;ode</text></g><g id="&#34;a\\node&#34;"><g class="shape" ><rect x="1072" y="8" width="155" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1149.500000" y="74.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\node</text></g><g id="(&#34;a\\yode&#34; -&gt; there)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 721.000000 136.000000 C 721.000000 180.400000 749.500000 207.049065 859.962840 265.377574" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1203581638)"/></g><g id="(&#39;a\&#34;ode&#39; -&gt; there)[0]"><path d="M 935.000000 136.000000 C 935.000000 180.400000 935.000000 202.000000 935.000000 238.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1203581638)"/></g><g id="(&#34;a\\node&#34; -&gt; there)[0]"><path d="M 1149.500000 136.000000 C 1149.500000 180.400000 1120.900000 207.000000 1010.042356 265.142121" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1203581638)"/></g><mask id="1203581638" maskUnits="userSpaceOnUse" x="-100" y="-100" width="1431" height="572">
<rect x="-100" y="-100" width="1431" height="572" fill="white"></rect>
]]></script><g id="&#34;ninety\nnine&#34;"><g class="shape" ><rect x="0" y="0" width="91" height="82" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="45.500000" y="38.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="45.500000" dy="0.000000">ninety</tspan><tspan x="45.500000" dy="18.500000">nine</tspan></text></g><g id="eighty&#xD;eight"><g class="shape" ><rect x="151" y="8" width="91" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="196.500000" y="46.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">eighty&#xD;eight</text></g><g id="&#34;seventy&#xD;\nseven&#34;"><g class="shape" ><rect x="302" y="0" width="102" height="82" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="353.000000" y="38.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="353.000000" dy="0.000000">seventy&#xD;</tspan><tspan x="353.000000" dy="18.500000">seven</tspan></text></g><g id="&#34;a\\yode&#34;"><g class="shape" ><rect x="464" y="8" width="94" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="511.000000" y="46.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\yode</text></g><g id="there"><g class="shape" ><rect x="624" y="182" width="83" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="665.500000" y="220.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">there</text></g><g id="&#39;a\&#34;ode&#39;"><g class="shape" ><rect x="618" y="8" width="94" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="665.000000" y="46.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\&#34;ode</text></g><g id="&#34;a\\node&#34;"><g class="shape" ><rect x="772" y="8" width="95" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="819.500000" y="46.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\node</text></g><g id="(&#34;a\\yode&#34; -&gt; there)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 511.000000 76.000000 C 511.000000 120.400000 533.500000 144.126623 619.978850 190.735354" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1631294189)"/></g><g id="(&#39;a\&#34;ode&#39; -&gt; there)[0]"><path d="M 665.000000 76.000000 C 665.000000 120.400000 665.000000 142.000000 665.000000 178.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1631294189)"/></g><g id="(&#34;a\\node&#34; -&gt; there)[0]"><path d="M 819.500000 76.000000 C 819.500000 120.400000 796.900000 144.000000 710.032868 190.124141" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1631294189)"/></g><mask id="1631294189" maskUnits="userSpaceOnUse" x="-100" y="-100" width="1071" height="452">
<rect x="-100" y="-100" width="1071" height="452" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text-bold {

Before

Width:  |  Height:  |  Size: 327 KiB

After

Width:  |  Height:  |  Size: 327 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "\"ninety\\nnine\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 151,
"height": 142,
"width": 91,
"height": 82,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 51,
"labelHeight": 42,
"labelWidth": 46,
"labelHeight": 37,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "eighty\reight",
"type": "",
"type": "rectangle",
"pos": {
"x": 183,
"x": 123,
"y": 20
},
"width": 151,
"height": 126,
"width": 91,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 51,
"labelHeight": 26,
"labelWidth": 46,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "\"seventy\r\\nseven\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 354,
"x": 234,
"y": 12
},
"width": 162,
"height": 142,
"width": 102,
"height": 82,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,21 +119,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 62,
"labelHeight": 42,
"labelWidth": 57,
"labelHeight": 37,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "\"a\\\\yode\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 536,
"x": 356,
"y": 28
},
"width": 154,
"height": 126,
"width": 94,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 54,
"labelHeight": 26,
"labelWidth": 49,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "there",
"type": "",
"type": "rectangle",
"pos": {
"x": 715,
"y": 254
"x": 475,
"y": 194
},
"width": 143,
"height": 126,
"width": 83,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +201,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 43,
"labelHeight": 26,
"labelWidth": 38,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "'a\\\"ode'",
"type": "",
"type": "rectangle",
"pos": {
"x": 710,
"x": 470,
"y": 28
},
"width": 154,
"height": 126,
"width": 94,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,21 +242,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 54,
"labelHeight": 26,
"labelWidth": 49,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "\"a\\\\node\"",
"type": "",
"type": "rectangle",
"pos": {
"x": 884,
"x": 584,
"y": 28
},
"width": 155,
"height": 126,
"width": 95,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -283,8 +283,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 26,
"labelWidth": 50,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -317,20 +317,20 @@
"labelPercentage": 0,
"route": [
{
"x": 613,
"y": 154
"x": 403,
"y": 94
},
{
"x": 613,
"y": 204
"x": 403,
"y": 144
},
{
"x": 751.25,
"y": 204
"x": 496.25,
"y": 144
},
{
"x": 751.25,
"y": 254
"x": 496.25,
"y": 194
}
],
"animated": false,
@ -364,12 +364,12 @@
"labelPercentage": 0,
"route": [
{
"x": 787,
"y": 154
"x": 517,
"y": 94
},
{
"x": 787,
"y": 254
"x": 517,
"y": 194
}
],
"animated": false,
@ -403,20 +403,20 @@
"labelPercentage": 0,
"route": [
{
"x": 961.5,
"y": 154
"x": 631.5,
"y": 94
},
{
"x": 961.5,
"y": 204
"x": 631.5,
"y": 144
},
{
"x": 822.75,
"y": 204
"x": 537.75,
"y": 144
},
{
"x": 822.75,
"y": 254
"x": 537.75,
"y": 194
}
],
"animated": false,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="1231" height="572" viewBox="-90 -90 1231 572"><style type="text/css">
width="871" height="452" viewBox="-90 -90 871 452"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,8 +39,8 @@ width="1231" height="572" viewBox="-90 -90 1231 572"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="&#34;ninety\nnine&#34;"><g class="shape" ><rect x="12" y="12" width="151" height="142" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="87.500000" y="78.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="87.500000" dy="0.000000">ninety</tspan><tspan x="87.500000" dy="21.000000">nine</tspan></text></g><g id="eighty&#xD;eight"><g class="shape" ><rect x="183" y="20" width="151" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="258.500000" y="86.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">eighty&#xD;eight</text></g><g id="&#34;seventy&#xD;\nseven&#34;"><g class="shape" ><rect x="354" y="12" width="162" height="142" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="435.000000" y="78.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="435.000000" dy="0.000000">seventy&#xD;</tspan><tspan x="435.000000" dy="21.000000">seven</tspan></text></g><g id="&#34;a\\yode&#34;"><g class="shape" ><rect x="536" y="28" width="154" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="613.000000" y="94.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\yode</text></g><g id="there"><g class="shape" ><rect x="715" y="254" width="143" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="786.500000" y="320.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">there</text></g><g id="&#39;a\&#34;ode&#39;"><g class="shape" ><rect x="710" y="28" width="154" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="787.000000" y="94.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\&#34;ode</text></g><g id="&#34;a\\node&#34;"><g class="shape" ><rect x="884" y="28" width="155" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="961.500000" y="94.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\node</text></g><g id="(&#34;a\\yode&#34; -&gt; there)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 613.000000 156.000000 L 613.000000 194.000000 S 613.000000 204.000000 623.000000 204.000000 L 741.250000 204.000000 S 751.250000 204.000000 751.250000 214.000000 L 751.250000 250.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#3116272567)"/></g><g id="(&#39;a\&#34;ode&#39; -&gt; there)[0]"><path d="M 787.000000 156.000000 L 787.000000 250.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#3116272567)"/></g><g id="(&#34;a\\node&#34; -&gt; there)[0]"><path d="M 961.500000 156.000000 L 961.500000 194.000000 S 961.500000 204.000000 951.500000 204.000000 L 832.750000 204.000000 S 822.750000 204.000000 822.750000 214.000000 L 822.750000 250.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#3116272567)"/></g><mask id="3116272567" maskUnits="userSpaceOnUse" x="-100" y="-100" width="1231" height="572">
<rect x="-100" y="-100" width="1231" height="572" fill="white"></rect>
]]></script><g id="&#34;ninety\nnine&#34;"><g class="shape" ><rect x="12" y="12" width="91" height="82" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="57.500000" y="50.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="57.500000" dy="0.000000">ninety</tspan><tspan x="57.500000" dy="18.500000">nine</tspan></text></g><g id="eighty&#xD;eight"><g class="shape" ><rect x="123" y="20" width="91" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="168.500000" y="58.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">eighty&#xD;eight</text></g><g id="&#34;seventy&#xD;\nseven&#34;"><g class="shape" ><rect x="234" y="12" width="102" height="82" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="285.000000" y="50.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25"><tspan x="285.000000" dy="0.000000">seventy&#xD;</tspan><tspan x="285.000000" dy="18.500000">seven</tspan></text></g><g id="&#34;a\\yode&#34;"><g class="shape" ><rect x="356" y="28" width="94" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="403.000000" y="66.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\yode</text></g><g id="there"><g class="shape" ><rect x="475" y="194" width="83" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="516.500000" y="232.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">there</text></g><g id="&#39;a\&#34;ode&#39;"><g class="shape" ><rect x="470" y="28" width="94" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="517.000000" y="66.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\&#34;ode</text></g><g id="&#34;a\\node&#34;"><g class="shape" ><rect x="584" y="28" width="95" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="631.500000" y="66.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a\node</text></g><g id="(&#34;a\\yode&#34; -&gt; there)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 403.000000 96.000000 L 403.000000 134.000000 S 403.000000 144.000000 413.000000 144.000000 L 486.250000 144.000000 S 496.250000 144.000000 496.250000 154.000000 L 496.250000 190.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1355253866)"/></g><g id="(&#39;a\&#34;ode&#39; -&gt; there)[0]"><path d="M 517.000000 96.000000 L 517.000000 190.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1355253866)"/></g><g id="(&#34;a\\node&#34; -&gt; there)[0]"><path d="M 631.500000 96.000000 L 631.500000 134.000000 S 631.500000 144.000000 621.500000 144.000000 L 547.750000 144.000000 S 537.750000 144.000000 537.750000 154.000000 L 537.750000 190.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1355253866)"/></g><mask id="1355253866" maskUnits="userSpaceOnUse" x="-100" y="-100" width="871" height="452">
<rect x="-100" y="-100" width="871" height="452" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text-bold {

Before

Width:  |  Height:  |  Size: 328 KiB

After

Width:  |  Height:  |  Size: 327 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "build_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 430,
"height": 1672,
"width": 370,
"height": 1372,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 226,
"labelHeight": 41,
"labelWidth": 221,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "build_workflow.push",
"type": "",
"type": "rectangle",
"pos": {
"x": 50,
"y": 73
},
"width": 330,
"height": 137,
"width": 270,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 230,
"labelHeight": 37,
"labelWidth": 225,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 81,
"y": 382
"y": 322
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,21 +119,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.S3",
"type": "",
"type": "rectangle",
"pos": {
"x": 150,
"y": 771
"y": 651
},
"width": 131,
"height": 137,
"width": 71,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 31,
"labelHeight": 37,
"labelWidth": 26,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.Terraform",
"type": "",
"type": "rectangle",
"pos": {
"x": 106,
"y": 1153
"y": 973
},
"width": 218,
"height": 137,
"width": 158,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +201,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 118,
"labelHeight": 37,
"labelWidth": 113,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 138,
"y": 1462
"y": 1222
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,21 +242,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "deploy_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 470,
"x": 410,
"y": 0
},
"width": 371,
"height": 981,
"width": 311,
"height": 801,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -283,21 +283,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 247,
"labelHeight": 41,
"labelWidth": 242,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "deploy_workflow.manual",
"type": "",
"type": "rectangle",
"pos": {
"x": 520,
"x": 460,
"y": 73
},
"width": 271,
"height": 137,
"width": 211,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -324,21 +324,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 171,
"labelHeight": 37,
"labelWidth": 166,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "deploy_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 521,
"y": 382
"x": 461,
"y": 322
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -365,21 +365,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "deploy_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 578,
"y": 771
"x": 518,
"y": 651
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -406,21 +406,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "apollo_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 881,
"x": 761,
"y": 0
},
"width": 613,
"height": 981,
"height": 801,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -447,21 +447,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 232,
"labelHeight": 41,
"labelWidth": 227,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "apollo_workflow.apollo",
"type": "",
"type": "rectangle",
"pos": {
"x": 1069,
"x": 979,
"y": 73
},
"width": 238,
"height": 137,
"width": 178,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -488,21 +488,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 138,
"labelHeight": 37,
"labelWidth": 133,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "apollo_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 1053,
"y": 382
"x": 963,
"y": 322
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -529,21 +529,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "apollo_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 1110,
"y": 771
"x": 1020,
"y": 651
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -570,8 +570,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -604,20 +604,20 @@
"labelPercentage": 0,
"route": [
{
"x": 215,
"y": 210
"x": 185,
"y": 150
},
{
"x": 215,
"y": 278.8
"x": 185,
"y": 218.8
},
{
"x": 215,
"y": 313.2
"x": 185,
"y": 253.2
},
{
"x": 215,
"y": 382
"x": 185,
"y": 322
}
],
"isCurve": true,
@ -652,20 +652,20 @@
"labelPercentage": 0,
"route": [
{
"x": 215,
"y": 519
"x": 185,
"y": 399
},
{
"x": 215,
"y": 619.8
"x": 185,
"y": 499.8
},
{
"x": 215,
"y": 670.2
"x": 185,
"y": 550.2
},
{
"x": 215,
"y": 771
"x": 185,
"y": 651
}
],
"isCurve": true,
@ -700,20 +700,20 @@
"labelPercentage": 0,
"route": [
{
"x": 215,
"y": 908
"x": 185,
"y": 728
},
{
"x": 215,
"y": 966.4
"x": 185,
"y": 786.4
},
{
"x": 215,
"y": 1084.2
"x": 185,
"y": 904.2
},
{
"x": 215,
"y": 1153
"x": 185,
"y": 973
}
],
"isCurve": true,
@ -748,20 +748,20 @@
"labelPercentage": 0,
"route": [
{
"x": 215,
"y": 1290
"x": 185,
"y": 1050
},
{
"x": 215,
"y": 1358.8
"x": 185,
"y": 1118.8
},
{
"x": 215,
"y": 1393.2
"x": 185,
"y": 1153.2
},
{
"x": 215,
"y": 1462
"x": 185,
"y": 1222
}
],
"isCurve": true,
@ -796,20 +796,20 @@
"labelPercentage": 0,
"route": [
{
"x": 655.5,
"y": 210
"x": 565.5,
"y": 150
},
{
"x": 655.5,
"y": 278.8
"x": 565.5,
"y": 218.8
},
{
"x": 655.5,
"y": 313.2
"x": 565.5,
"y": 253.2
},
{
"x": 655.5,
"y": 382
"x": 565.5,
"y": 322
}
],
"isCurve": true,
@ -844,20 +844,20 @@
"labelPercentage": 0,
"route": [
{
"x": 655.5,
"y": 519
"x": 565.5,
"y": 399
},
{
"x": 655.5,
"y": 619.8
"x": 565.5,
"y": 499.8
},
{
"x": 655.5,
"y": 670.2
"x": 565.5,
"y": 550.2
},
{
"x": 655.5,
"y": 771
"x": 565.5,
"y": 651
}
],
"isCurve": true,
@ -892,20 +892,20 @@
"labelPercentage": 0,
"route": [
{
"x": 1187.5,
"y": 210
"x": 1067.5,
"y": 150
},
{
"x": 1187.5,
"y": 278.8
"x": 1067.5,
"y": 218.8
},
{
"x": 1187.5,
"y": 313.2
"x": 1067.5,
"y": 253.2
},
{
"x": 1187.5,
"y": 382
"x": 1067.5,
"y": 322
}
],
"isCurve": true,
@ -940,20 +940,20 @@
"labelPercentage": 0,
"route": [
{
"x": 1187.5,
"y": 519
"x": 1067.5,
"y": 399
},
{
"x": 1187.5,
"y": 619.8
"x": 1067.5,
"y": 499.8
},
{
"x": 1187.5,
"y": 670.2
"x": 1067.5,
"y": 550.2
},
{
"x": 1187.5,
"y": 771
"x": 1067.5,
"y": 651
}
],
"isCurve": true,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 799 KiB

After

Width:  |  Height:  |  Size: 799 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "build_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 480,
"height": 1739,
"width": 420,
"height": 1439,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 226,
"labelHeight": 41,
"labelWidth": 221,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "build_workflow.push",
"type": "",
"type": "rectangle",
"pos": {
"x": 87,
"y": 87
},
"width": 330,
"height": 137,
"width": 270,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 230,
"labelHeight": 37,
"labelWidth": 225,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 117,
"y": 450
"y": 390
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,21 +119,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.S3",
"type": "",
"type": "rectangle",
"pos": {
"x": 186,
"y": 813
"y": 693
},
"width": 131,
"height": 137,
"width": 71,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -160,21 +160,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 31,
"labelHeight": 37,
"labelWidth": 26,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.Terraform",
"type": "",
"type": "rectangle",
"pos": {
"x": 143,
"y": 1176
"y": 996
},
"width": 218,
"height": 137,
"width": 158,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -201,21 +201,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 118,
"labelHeight": 37,
"labelWidth": 113,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "build_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 174,
"y": 1539
"y": 1299
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -242,21 +242,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "deploy_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 512,
"y": 335
"x": 452,
"y": 275
},
"width": 421,
"height": 1093,
"width": 361,
"height": 913,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -283,21 +283,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 247,
"labelHeight": 41,
"labelWidth": 242,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "deploy_workflow.manual",
"type": "",
"type": "rectangle",
"pos": {
"x": 587,
"y": 410
"x": 527,
"y": 350
},
"width": 271,
"height": 137,
"width": 211,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -324,21 +324,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 171,
"labelHeight": 37,
"labelWidth": 166,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "deploy_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 588,
"y": 773
"x": 528,
"y": 653
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -365,21 +365,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "deploy_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 645,
"y": 1216
"x": 585,
"y": 1036
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -406,21 +406,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "apollo_workflow",
"type": "",
"type": "rectangle",
"pos": {
"x": 953,
"y": 375
"x": 833,
"y": 315
},
"width": 684,
"height": 1013,
"height": 833,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -447,21 +447,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 232,
"labelHeight": 41,
"labelWidth": 227,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "apollo_workflow.apollo",
"type": "",
"type": "rectangle",
"pos": {
"x": 1175,
"y": 450
"x": 1085,
"y": 390
},
"width": 238,
"height": 137,
"width": 178,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -488,21 +488,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 138,
"labelHeight": 37,
"labelWidth": 133,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "apollo_workflow.GHA",
"type": "",
"type": "rectangle",
"pos": {
"x": 1160,
"y": 813
"x": 1070,
"y": 693
},
"width": 269,
"height": 137,
"width": 209,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -529,21 +529,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 169,
"labelHeight": 37,
"labelWidth": 164,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "apollo_workflow.AWS",
"type": "",
"type": "rectangle",
"pos": {
"x": 1217,
"y": 1176
"x": 1127,
"y": 996
},
"width": 155,
"height": 137,
"width": 95,
"height": 77,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -570,8 +570,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 55,
"labelHeight": 37,
"labelWidth": 50,
"labelHeight": 32,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -604,12 +604,12 @@
"labelPercentage": 0,
"route": [
{
"x": 252,
"y": 224
"x": 222,
"y": 164
},
{
"x": 252,
"y": 450
"x": 222,
"y": 390
}
],
"animated": false,
@ -643,12 +643,12 @@
"labelPercentage": 0,
"route": [
{
"x": 252,
"y": 587
"x": 222,
"y": 467
},
{
"x": 252,
"y": 813
"x": 222,
"y": 693
}
],
"animated": false,
@ -682,12 +682,12 @@
"labelPercentage": 0,
"route": [
{
"x": 252,
"y": 950
"x": 222,
"y": 770
},
{
"x": 252,
"y": 1176
"x": 222,
"y": 996
}
],
"animated": false,
@ -721,12 +721,12 @@
"labelPercentage": 0,
"route": [
{
"x": 252,
"y": 1313
"x": 222,
"y": 1073
},
{
"x": 252,
"y": 1539
"x": 222,
"y": 1299
}
],
"animated": false,
@ -760,12 +760,12 @@
"labelPercentage": 0,
"route": [
{
"x": 722.5,
"y": 547
"x": 632.5,
"y": 427
},
{
"x": 722.5,
"y": 773
"x": 632.5,
"y": 653
}
],
"animated": false,
@ -799,12 +799,12 @@
"labelPercentage": 0,
"route": [
{
"x": 722.5,
"y": 910
"x": 632.5,
"y": 730
},
{
"x": 722.5,
"y": 1216
"x": 632.5,
"y": 1036
}
],
"animated": false,
@ -838,12 +838,12 @@
"labelPercentage": 0,
"route": [
{
"x": 1294.5,
"y": 587
"x": 1174.5,
"y": 467
},
{
"x": 1294.5,
"y": 813
"x": 1174.5,
"y": 693
}
],
"animated": false,
@ -877,12 +877,12 @@
"labelPercentage": 0,
"route": [
{
"x": 1294.5,
"y": 950
"x": 1174.5,
"y": 770
},
{
"x": 1294.5,
"y": 1176
"x": 1174.5,
"y": 996
}
],
"animated": false,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 799 KiB

After

Width:  |  Height:  |  Size: 799 KiB

View file

@ -55,7 +55,7 @@
},
{
"id": "ico",
"type": "",
"type": "rectangle",
"pos": {
"x": 188,
"y": 14

View file

@ -39,7 +39,7 @@ width="492" height="332" viewBox="-102 -102 492 332"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="img"><g class="shape" ><image href="https://icons.terrastruct.com/infra/019-network.svg" x="0" y="0" width="128" height="128" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:2;" /></g></g><g id="ico"><g class="shape" ><rect x="188" y="14" width="100" height="100" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><image href="https://icons.terrastruct.com/infra/019-network.svg" x="213.000000" y="39.000000" width="50" height="50" /></g><mask id="1658185428" maskUnits="userSpaceOnUse" x="-100" y="-100" width="492" height="332">
]]></script><g id="img"><g class="shape" ><image href="https://icons.terrastruct.com/infra/019-network.svg" x="0" y="0" width="128" height="128" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:2;" /></g></g><g id="ico"><g class="shape" ><rect x="188" y="14" width="100" height="100" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><image href="https://icons.terrastruct.com/infra/019-network.svg" x="213.000000" y="39.000000" width="50" height="50" /></g><mask id="2468208653" maskUnits="userSpaceOnUse" x="-100" y="-100" width="492" height="332">
<rect x="-100" y="-100" width="492" height="332" fill="white"></rect>
</mask><style type="text/css"><![CDATA[]]></style></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -55,7 +55,7 @@
},
{
"id": "ico",
"type": "",
"type": "rectangle",
"pos": {
"x": 160,
"y": 26

View file

@ -39,7 +39,7 @@ width="452" height="332" viewBox="-90 -90 452 332"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="img"><g class="shape" ><image href="https://icons.terrastruct.com/infra/019-network.svg" x="12" y="12" width="128" height="128" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:2;" /></g></g><g id="ico"><g class="shape" ><rect x="160" y="26" width="100" height="100" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><image href="https://icons.terrastruct.com/infra/019-network.svg" x="185.000000" y="51.000000" width="50" height="50" /></g><mask id="2006067969" maskUnits="userSpaceOnUse" x="-100" y="-100" width="452" height="332">
]]></script><g id="img"><g class="shape" ><image href="https://icons.terrastruct.com/infra/019-network.svg" x="12" y="12" width="128" height="128" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:2;" /></g></g><g id="ico"><g class="shape" ><rect x="160" y="26" width="100" height="100" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><image href="https://icons.terrastruct.com/infra/019-network.svg" x="185.000000" y="51.000000" width="50" height="50" /></g><mask id="882453984" maskUnits="userSpaceOnUse" x="-100" y="-100" width="452" height="332">
<rect x="-100" y="-100" width="452" height="332" fill="white"></rect>
</mask><style type="text/css"><![CDATA[]]></style></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "x",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 426,
"height": 226,
"width": 306,
"height": 166,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 18,
"labelHeight": 41,
"labelWidth": 13,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "x.a",
"type": "",
"type": "rectangle",
"pos": {
"x": 50,
"y": 50
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "x.b",
"type": "",
"type": "rectangle",
"pos": {
"x": 263,
"x": 203,
"y": 50
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,8 +119,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -153,56 +153,56 @@
"labelPercentage": 0,
"route": [
{
"x": 163,
"y": 73.37662337662337
"x": 103,
"y": 68.38440111420613
},
{
"x": 189.66666666666669,
"y": 54.675324675324674
"x": 129.66666666666669,
"y": 53.67688022284123
},
{
"x": 198,
"x": 138,
"y": 50
},
{
"x": 200.5,
"x": 140.5,
"y": 50
},
{
"x": 203,
"x": 143,
"y": 50
},
{
"x": 206.33333333333331,
"y": 62.6
"x": 146.33333333333331,
"y": 56.6
},
{
"x": 208.83333333333331,
"y": 81.5
"x": 148.83333333333331,
"y": 66.5
},
{
"x": 211.33333333333334,
"y": 100.4
"x": 151.33333333333334,
"y": 76.4
},
{
"x": 211.33333333333334,
"y": 125.6
"x": 151.33333333333334,
"y": 89.6
},
{
"x": 208.83333333333331,
"y": 144.5
"x": 148.83333333333331,
"y": 99.5
},
{
"x": 206.33333333333331,
"y": 163.4
"x": 146.33333333333331,
"y": 109.4
},
{
"x": 189.66666666666669,
"y": 171.32467532467533
"x": 129.66666666666669,
"y": 112.32311977715878
},
{
"x": 163,
"y": 152.62337662337663
"x": 103,
"y": 97.61559888579387
}
],
"isCurve": true,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="630" height="430" viewBox="-102 -102 630 430"><style type="text/css">
width="510" height="370" viewBox="-102 -102 510 370"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,8 +39,8 @@ width="630" height="430" viewBox="-102 -102 630 430"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="x"><g class="shape" ><rect x="0" y="0" width="426" height="226" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="213.000000" y="33.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">x</text></g><g id="x.a"><g class="shape" ><rect x="50" y="50" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="106.500000" y="116.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="x.b"><g class="shape" ><rect x="263" y="50" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="319.500000" y="116.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="x.(a -&gt; a)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 164.637464 72.228272 C 189.666667 54.675325 198.000000 50.000000 200.500000 50.000000 C 203.000000 50.000000 206.333333 62.600000 208.833333 81.500000 C 211.333333 100.400000 211.333333 125.600000 208.833333 144.500000 C 206.333333 163.400000 189.666667 171.324675 166.274928 154.920080" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#4032396985)"/></g><mask id="4032396985" maskUnits="userSpaceOnUse" x="-100" y="-100" width="630" height="430">
<rect x="-100" y="-100" width="630" height="430" fill="white"></rect>
]]></script><g id="x"><g class="shape" ><rect x="0" y="0" width="306" height="166" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="153.000000" y="33.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">x</text></g><g id="x.a"><g class="shape" ><rect x="50" y="50" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="76.500000" y="88.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="x.b"><g class="shape" ><rect x="203" y="50" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="229.500000" y="88.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="x.(a -&gt; a)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 104.751298 67.418504 C 129.666667 53.676880 138.000000 50.000000 140.500000 50.000000 C 143.000000 50.000000 146.333333 56.600000 148.833333 66.500000 C 151.333333 76.400000 151.333333 89.600000 148.833333 99.500000 C 146.333333 109.400000 129.666667 112.323120 106.502595 99.547392" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2444376964)"/></g><mask id="2444376964" maskUnits="userSpaceOnUse" x="-100" y="-100" width="510" height="370">
<rect x="-100" y="-100" width="510" height="370" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text {

Before

Width:  |  Height:  |  Size: 649 KiB

After

Width:  |  Height:  |  Size: 649 KiB

View file

@ -4,13 +4,13 @@
"shapes": [
{
"id": "x",
"type": "",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 446,
"height": 276,
"width": 326,
"height": 216,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -37,21 +37,21 @@
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 18,
"labelHeight": 41,
"labelWidth": 13,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "x.a",
"type": "",
"type": "rectangle",
"pos": {
"x": 137,
"y": 87
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -78,21 +78,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "x.b",
"type": "",
"type": "rectangle",
"pos": {
"x": 270,
"x": 210,
"y": 87
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -119,8 +119,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -154,19 +154,19 @@
"route": [
{
"x": 137,
"y": 129
"y": 109
},
{
"x": 87,
"y": 129
"y": 109
},
{
"x": 87,
"y": 171
"y": 131
},
{
"x": 137,
"y": 171
"y": 131
}
],
"animated": false,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="650" height="480" viewBox="-90 -90 650 480"><style type="text/css">
width="530" height="420" viewBox="-90 -90 530 420"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,8 +39,8 @@ width="650" height="480" viewBox="-90 -90 650 480"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="x"><g class="shape" ><rect x="12" y="12" width="446" height="276" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="235.000000" y="45.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">x</text></g><g id="x.a"><g class="shape" ><rect x="137" y="87" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="193.500000" y="153.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="x.b"><g class="shape" ><rect x="270" y="87" width="113" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="326.500000" y="153.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="x.(a -&gt; a)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 135.000000 129.000000 L 97.000000 129.000000 S 87.000000 129.000000 87.000000 139.000000 L 87.000000 161.000000 S 87.000000 171.000000 97.000000 171.000000 L 133.000000 171.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#108613724)"/></g><mask id="108613724" maskUnits="userSpaceOnUse" x="-100" y="-100" width="650" height="480">
<rect x="-100" y="-100" width="650" height="480" fill="white"></rect>
]]></script><g id="x"><g class="shape" ><rect x="12" y="12" width="326" height="216" style="fill:#E3E9FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text" x="175.000000" y="45.000000" style="text-anchor:middle;font-size:28px;fill:#0A0F25">x</text></g><g id="x.a"><g class="shape" ><rect x="137" y="87" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="163.500000" y="125.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="x.b"><g class="shape" ><rect x="210" y="87" width="53" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="236.500000" y="125.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="x.(a -&gt; a)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 135.000000 109.000000 L 97.000000 109.000000 S 87.000000 109.000000 87.000000 119.000000 L 87.000000 121.000000 S 87.000000 131.000000 97.000000 131.000000 L 133.000000 131.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#672125111)"/></g><mask id="672125111" maskUnits="userSpaceOnUse" x="-100" y="-100" width="530" height="420">
<rect x="-100" y="-100" width="530" height="420" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text {

Before

Width:  |  Height:  |  Size: 649 KiB

After

Width:  |  Height:  |  Size: 649 KiB

View file

@ -9,8 +9,8 @@
"x": 0,
"y": 148
},
"width": 1336,
"height": 226,
"width": 966,
"height": 166,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -44,13 +44,13 @@
},
{
"id": "queue.M0",
"type": "",
"type": "rectangle",
"pos": {
"x": 50,
"y": 198
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -77,21 +77,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M1",
"type": "",
"type": "rectangle",
"pos": {
"x": 235,
"x": 175,
"y": 198
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -118,21 +118,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M2",
"type": "",
"type": "rectangle",
"pos": {
"x": 420,
"x": 300,
"y": 198
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -159,21 +159,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M3",
"type": "",
"type": "rectangle",
"pos": {
"x": 605,
"x": 425,
"y": 198
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -200,21 +200,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M4",
"type": "",
"type": "rectangle",
"pos": {
"x": 790,
"x": 550,
"y": 198
},
"width": 126,
"height": 126,
"width": 66,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -241,21 +241,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 26,
"labelHeight": 26,
"labelWidth": 21,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M5",
"type": "",
"type": "rectangle",
"pos": {
"x": 976,
"x": 676,
"y": 198
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -282,21 +282,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M6",
"type": "",
"type": "rectangle",
"pos": {
"x": 1161,
"x": 851,
"y": 198
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -323,8 +323,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -333,7 +333,7 @@
"id": "m0_desc",
"type": "text",
"pos": {
"x": 60,
"x": 30,
"y": 12
},
"width": 106,
@ -373,7 +373,7 @@
"id": "m2_desc",
"type": "text",
"pos": {
"x": 462,
"x": 312,
"y": 12
},
"width": 41,
@ -413,7 +413,7 @@
"id": "m5_desc",
"type": "text",
"pos": {
"x": 994,
"x": 664,
"y": 12
},
"width": 90,
@ -453,7 +453,7 @@
"id": "m6_desc",
"type": "text",
"pos": {
"x": 1154,
"x": 814,
"y": 0
},
"width": 140,
@ -517,19 +517,19 @@
"labelPercentage": 0,
"route": [
{
"x": 112.5,
"x": 82.5,
"y": 36
},
{
"x": 112.5,
"x": 82.5,
"y": 85.6
},
{
"x": 112.5,
"x": 82.5,
"y": 158
},
{
"x": 112.5,
"x": 82.5,
"y": 198
}
],
@ -565,19 +565,19 @@
"labelPercentage": 0,
"route": [
{
"x": 482.5,
"x": 332.5,
"y": 36
},
{
"x": 482.5,
"x": 332.5,
"y": 85.6
},
{
"x": 482.5,
"x": 332.5,
"y": 158
},
{
"x": 482.5,
"x": 332.5,
"y": 198
}
],
@ -613,19 +613,19 @@
"labelPercentage": 0,
"route": [
{
"x": 1038.5,
"x": 708.5,
"y": 36
},
{
"x": 1038.5,
"x": 708.5,
"y": 85.6
},
{
"x": 1038.5,
"x": 708.5,
"y": 158
},
{
"x": 1038.5,
"x": 708.5,
"y": 198
}
],
@ -661,19 +661,19 @@
"labelPercentage": 0,
"route": [
{
"x": 1223.5,
"x": 883.5,
"y": 48
},
{
"x": 1223.5,
"x": 883.5,
"y": 88
},
{
"x": 1223.5,
"x": 883.5,
"y": 158
},
{
"x": 1223.5,
"x": 883.5,
"y": 198
}
],

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="1540" height="578" viewBox="-102 -102 1540 578"><style type="text/css">
width="1170" height="518" viewBox="-102 -102 1170 518"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -796,13 +796,13 @@ width="1540" height="578" viewBox="-102 -102 1540 578"><style type="text/css">
.md .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em 0.25em 0.2em;
}
</style><g id="queue"><g class="shape" ><path d="M 24 148 H 1312 C 1336 148 1336 249.7 1336 261 C 1336 272.3 1336 374 1312 374 H 24 C 0 374 0 272.3 0 261 C 0 249.7 0 148 24 148 Z" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/><path d="M 1312 148 C 1288 148 1288 249.7 1288 261 C 1288 272.3 1288 374 1312 374" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/></g></g><g id="m0_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="60.000000" y="12.000000" width="106" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Oldest message</p>
</div></foreignObject></g></g><g id="m2_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="462.000000" y="12.000000" width="41" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Offset</p>
</div></foreignObject></g></g><g id="m5_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="994.000000" y="12.000000" width="90" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Last message</p>
</div></foreignObject></g></g><g id="m6_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="1154.000000" y="0.000000" width="140" height="48"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Next message will be<br />
</style><g id="queue"><g class="shape" ><path d="M 24 148 H 942 C 966 148 966 223 966 231 C 966 239 966 314 942 314 H 24 C 0 314 0 239 0 231 C 0 223 0 148 24 148 Z" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/><path d="M 942 148 C 918 148 918 223 918 231 C 918 239 918 314 942 314" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/></g></g><g id="m0_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="30.000000" y="12.000000" width="106" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Oldest message</p>
</div></foreignObject></g></g><g id="m2_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="312.000000" y="12.000000" width="41" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Offset</p>
</div></foreignObject></g></g><g id="m5_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="664.000000" y="12.000000" width="90" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Last message</p>
</div></foreignObject></g></g><g id="m6_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="814.000000" y="0.000000" width="140" height="48"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Next message will be<br />
inserted here</p>
</div></foreignObject></g></g><g id="queue.M0"><g class="shape" ><rect x="50" y="198" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="112.500000" y="264.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M0</text></g><g id="queue.M1"><g class="shape" ><rect x="235" y="198" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="297.500000" y="264.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M1</text></g><g id="queue.M2"><g class="shape" ><rect x="420" y="198" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="482.500000" y="264.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M2</text></g><g id="queue.M3"><g class="shape" ><rect x="605" y="198" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="667.500000" y="264.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M3</text></g><g id="queue.M4"><g class="shape" ><rect x="790" y="198" width="126" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="853.000000" y="264.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M4</text></g><g id="queue.M5"><g class="shape" ><rect x="976" y="198" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1038.500000" y="264.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M5</text></g><g id="queue.M6"><g class="shape" ><rect x="1161" y="198" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1223.500000" y="264.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M6</text></g><g id="(m0_desc -&gt; queue.M0)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 112.500000 38.000000 C 112.500000 85.600000 112.500000 158.000000 112.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2000745678)"/></g><g id="(m2_desc -&gt; queue.M2)[0]"><path d="M 482.500000 38.000000 C 482.500000 85.600000 482.500000 158.000000 482.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2000745678)"/></g><g id="(m5_desc -&gt; queue.M5)[0]"><path d="M 1038.500000 38.000000 C 1038.500000 85.600000 1038.500000 158.000000 1038.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2000745678)"/></g><g id="(m6_desc -&gt; queue.M6)[0]"><path d="M 1223.500000 50.000000 C 1223.500000 88.000000 1223.500000 158.000000 1223.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2000745678)"/></g><mask id="2000745678" maskUnits="userSpaceOnUse" x="-100" y="-100" width="1540" height="578">
<rect x="-100" y="-100" width="1540" height="578" fill="white"></rect>
</div></foreignObject></g></g><g id="queue.M0"><g class="shape" ><rect x="50" y="198" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="82.500000" y="236.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M0</text></g><g id="queue.M1"><g class="shape" ><rect x="175" y="198" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="207.500000" y="236.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M1</text></g><g id="queue.M2"><g class="shape" ><rect x="300" y="198" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="332.500000" y="236.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M2</text></g><g id="queue.M3"><g class="shape" ><rect x="425" y="198" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="457.500000" y="236.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M3</text></g><g id="queue.M4"><g class="shape" ><rect x="550" y="198" width="66" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="583.000000" y="236.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M4</text></g><g id="queue.M5"><g class="shape" ><rect x="676" y="198" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="708.500000" y="236.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M5</text></g><g id="queue.M6"><g class="shape" ><rect x="851" y="198" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="883.500000" y="236.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M6</text></g><g id="(m0_desc -&gt; queue.M0)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 82.500000 38.000000 C 82.500000 85.600000 82.500000 158.000000 82.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1051552217)"/></g><g id="(m2_desc -&gt; queue.M2)[0]"><path d="M 332.500000 38.000000 C 332.500000 85.600000 332.500000 158.000000 332.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1051552217)"/></g><g id="(m5_desc -&gt; queue.M5)[0]"><path d="M 708.500000 38.000000 C 708.500000 85.600000 708.500000 158.000000 708.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1051552217)"/></g><g id="(m6_desc -&gt; queue.M6)[0]"><path d="M 883.500000 50.000000 C 883.500000 88.000000 883.500000 158.000000 883.500000 194.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1051552217)"/></g><mask id="1051552217" maskUnits="userSpaceOnUse" x="-100" y="-100" width="1170" height="518">
<rect x="-100" y="-100" width="1170" height="518" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text {

Before

Width:  |  Height:  |  Size: 664 KiB

After

Width:  |  Height:  |  Size: 664 KiB

View file

@ -9,8 +9,8 @@
"x": 12,
"y": 165
},
"width": 1146,
"height": 276,
"width": 726,
"height": 216,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -44,13 +44,13 @@
},
{
"id": "queue.M0",
"type": "",
"type": "rectangle",
"pos": {
"x": 87,
"y": 240
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -77,21 +77,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M1",
"type": "",
"type": "rectangle",
"pos": {
"x": 232,
"x": 172,
"y": 240
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -118,21 +118,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M2",
"type": "",
"type": "rectangle",
"pos": {
"x": 377,
"x": 257,
"y": 240
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -159,21 +159,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M3",
"type": "",
"type": "rectangle",
"pos": {
"x": 522,
"x": 342,
"y": 240
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -200,21 +200,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M4",
"type": "",
"type": "rectangle",
"pos": {
"x": 667,
"x": 427,
"y": 240
},
"width": 126,
"height": 126,
"width": 66,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -241,21 +241,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 26,
"labelHeight": 26,
"labelWidth": 21,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M5",
"type": "",
"type": "rectangle",
"pos": {
"x": 813,
"x": 513,
"y": 240
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -282,21 +282,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "queue.M6",
"type": "",
"type": "rectangle",
"pos": {
"x": 958,
"x": 598,
"y": 240
},
"width": 125,
"height": 126,
"width": 65,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -323,8 +323,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 25,
"labelHeight": 26,
"labelWidth": 20,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
@ -333,7 +333,7 @@
"id": "m0_desc",
"type": "text",
"pos": {
"x": 96,
"x": 66,
"y": 36
},
"width": 106,
@ -373,7 +373,7 @@
"id": "m2_desc",
"type": "text",
"pos": {
"x": 419,
"x": 269,
"y": 36
},
"width": 41,
@ -413,7 +413,7 @@
"id": "m5_desc",
"type": "text",
"pos": {
"x": 830,
"x": 450,
"y": 36
},
"width": 90,
@ -453,7 +453,7 @@
"id": "m6_desc",
"type": "text",
"pos": {
"x": 950,
"x": 560,
"y": 12
},
"width": 140,
@ -517,11 +517,11 @@
"labelPercentage": 0,
"route": [
{
"x": 149.5,
"x": 119.5,
"y": 60
},
{
"x": 149.5,
"x": 119.5,
"y": 240
}
],
@ -556,11 +556,11 @@
"labelPercentage": 0,
"route": [
{
"x": 439.5,
"x": 289.5,
"y": 60
},
{
"x": 439.5,
"x": 289.5,
"y": 240
}
],
@ -595,11 +595,19 @@
"labelPercentage": 0,
"route": [
{
"x": 875.5,
"x": 495.5,
"y": 60
},
{
"x": 875.5,
"x": 495.5,
"y": 110
},
{
"x": 545.5,
"y": 110
},
{
"x": 545.5,
"y": 240
}
],
@ -634,11 +642,11 @@
"labelPercentage": 0,
"route": [
{
"x": 1020.5,
"x": 630.5,
"y": 60
},
{
"x": 1020.5,
"x": 630.5,
"y": 240
}
],

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="1350" height="633" viewBox="-90 -90 1350 633"><style type="text/css">
width="930" height="573" viewBox="-90 -90 930 573"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -796,13 +796,13 @@ width="1350" height="633" viewBox="-90 -90 1350 633"><style type="text/css">
.md .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em 0.25em 0.2em;
}
</style><g id="queue"><g class="shape" ><path d="M 36 165 H 1134 C 1158 165 1158 289.2 1158 303 C 1158 316.8 1158 441 1134 441 H 36 C 12 441 12 316.8 12 303 C 12 289.2 12 165 36 165 Z" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/><path d="M 1134 165 C 1110 165 1110 289.2 1110 303 C 1110 316.8 1110 441 1134 441" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/></g></g><g id="m0_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="96.000000" y="36.000000" width="106" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Oldest message</p>
</div></foreignObject></g></g><g id="m2_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="419.000000" y="36.000000" width="41" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Offset</p>
</div></foreignObject></g></g><g id="m5_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="830.000000" y="36.000000" width="90" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Last message</p>
</div></foreignObject></g></g><g id="m6_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="950.000000" y="12.000000" width="140" height="48"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Next message will be<br />
</style><g id="queue"><g class="shape" ><path d="M 36 165 H 714 C 738 165 738 262 738 273 C 738 284 738 381 714 381 H 36 C 12 381 12 284 12 273 C 12 262 12 165 36 165 Z" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/><path d="M 714 165 C 690 165 690 262 690 273 C 690 284 690 381 714 381" style="fill:#DEE1EB;stroke:#0D32B2;stroke-width:2;"/></g></g><g id="m0_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="66.000000" y="36.000000" width="106" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Oldest message</p>
</div></foreignObject></g></g><g id="m2_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="269.000000" y="36.000000" width="41" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Offset</p>
</div></foreignObject></g></g><g id="m5_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="450.000000" y="36.000000" width="90" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Last message</p>
</div></foreignObject></g></g><g id="m6_desc"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="560.000000" y="12.000000" width="140" height="48"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><p>Next message will be<br />
inserted here</p>
</div></foreignObject></g></g><g id="queue.M0"><g class="shape" ><rect x="87" y="240" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="149.500000" y="306.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M0</text></g><g id="queue.M1"><g class="shape" ><rect x="232" y="240" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="294.500000" y="306.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M1</text></g><g id="queue.M2"><g class="shape" ><rect x="377" y="240" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="439.500000" y="306.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M2</text></g><g id="queue.M3"><g class="shape" ><rect x="522" y="240" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="584.500000" y="306.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M3</text></g><g id="queue.M4"><g class="shape" ><rect x="667" y="240" width="126" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="730.000000" y="306.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M4</text></g><g id="queue.M5"><g class="shape" ><rect x="813" y="240" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="875.500000" y="306.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M5</text></g><g id="queue.M6"><g class="shape" ><rect x="958" y="240" width="125" height="126" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="1020.500000" y="306.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M6</text></g><g id="(m0_desc -&gt; queue.M0)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 149.500000 62.000000 L 149.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1429777714)"/></g><g id="(m2_desc -&gt; queue.M2)[0]"><path d="M 439.500000 62.000000 L 439.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1429777714)"/></g><g id="(m5_desc -&gt; queue.M5)[0]"><path d="M 875.500000 62.000000 L 875.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1429777714)"/></g><g id="(m6_desc -&gt; queue.M6)[0]"><path d="M 1020.500000 62.000000 L 1020.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#1429777714)"/></g><mask id="1429777714" maskUnits="userSpaceOnUse" x="-100" y="-100" width="1350" height="633">
<rect x="-100" y="-100" width="1350" height="633" fill="white"></rect>
</div></foreignObject></g></g><g id="queue.M0"><g class="shape" ><rect x="87" y="240" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="119.500000" y="278.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M0</text></g><g id="queue.M1"><g class="shape" ><rect x="172" y="240" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="204.500000" y="278.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M1</text></g><g id="queue.M2"><g class="shape" ><rect x="257" y="240" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="289.500000" y="278.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M2</text></g><g id="queue.M3"><g class="shape" ><rect x="342" y="240" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="374.500000" y="278.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M3</text></g><g id="queue.M4"><g class="shape" ><rect x="427" y="240" width="66" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="460.000000" y="278.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M4</text></g><g id="queue.M5"><g class="shape" ><rect x="513" y="240" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="545.500000" y="278.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M5</text></g><g id="queue.M6"><g class="shape" ><rect x="598" y="240" width="65" height="66" style="fill:#EDF0FD;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="630.500000" y="278.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">M6</text></g><g id="(m0_desc -&gt; queue.M0)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 119.500000 62.000000 L 119.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2142408228)"/></g><g id="(m2_desc -&gt; queue.M2)[0]"><path d="M 289.500000 62.000000 L 289.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2142408228)"/></g><g id="(m5_desc -&gt; queue.M5)[0]"><path d="M 495.500000 62.000000 L 495.500000 100.000000 S 495.500000 110.000000 505.500000 110.000000 L 535.500000 110.000000 S 545.500000 110.000000 545.500000 120.000000 L 545.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2142408228)"/></g><g id="(m6_desc -&gt; queue.M6)[0]"><path d="M 630.500000 62.000000 L 630.500000 236.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2142408228)"/></g><mask id="2142408228" maskUnits="userSpaceOnUse" x="-100" y="-100" width="930" height="573">
<rect x="-100" y="-100" width="930" height="573" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text {

Before

Width:  |  Height:  |  Size: 664 KiB

After

Width:  |  Height:  |  Size: 664 KiB

View file

@ -0,0 +1,104 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "class1",
"type": "class",
"pos": {
"x": 0,
"y": 0
},
"width": 319,
"height": 184,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#0A0F25",
"stroke": "#FFFFFF",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": [
{
"name": "num",
"type": "int",
"visibility": "private"
},
{
"name": "timeout",
"type": "int",
"visibility": "private"
}
],
"methods": null,
"columns": null,
"label": "class with rows",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 214,
"labelHeight": 31,
"zIndex": 0,
"level": 1,
"primaryAccentColor": "#0D32B2",
"secondaryAccentColor": "#4A6FF3",
"neutralAccentColor": "#676C7E"
},
{
"id": "class2",
"type": "class",
"pos": {
"x": 379,
"y": 46
},
"width": 362,
"height": 92,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#0A0F25",
"stroke": "#FFFFFF",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "class without rows",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 257,
"labelHeight": 31,
"zIndex": 0,
"level": 1,
"primaryAccentColor": "#0D32B2",
"secondaryAccentColor": "#4A6FF3",
"neutralAccentColor": "#676C7E"
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 184 KiB

View file

@ -0,0 +1,104 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "class1",
"type": "class",
"pos": {
"x": 12,
"y": 12
},
"width": 319,
"height": 184,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#0A0F25",
"stroke": "#FFFFFF",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": [
{
"name": "num",
"type": "int",
"visibility": "private"
},
{
"name": "timeout",
"type": "int",
"visibility": "private"
}
],
"methods": null,
"columns": null,
"label": "class with rows",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 214,
"labelHeight": 31,
"zIndex": 0,
"level": 1,
"primaryAccentColor": "#0D32B2",
"secondaryAccentColor": "#4A6FF3",
"neutralAccentColor": "#676C7E"
},
{
"id": "class2",
"type": "class",
"pos": {
"x": 351,
"y": 58
},
"width": 362,
"height": 92,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#0A0F25",
"stroke": "#FFFFFF",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "class without rows",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 257,
"labelHeight": 31,
"zIndex": 0,
"level": 1,
"primaryAccentColor": "#0D32B2",
"secondaryAccentColor": "#4A6FF3",
"neutralAccentColor": "#676C7E"
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 184 KiB

View file

@ -9,8 +9,8 @@
"x": 13,
"y": 0
},
"width": 140,
"height": 126,
"width": 80,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -37,8 +37,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 40,
"labelHeight": 26,
"labelWidth": 35,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -48,10 +48,10 @@
"type": "sequence_diagram",
"pos": {
"x": 0,
"y": 226
"y": 166
},
"width": 166,
"height": 126,
"width": 106,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -78,8 +78,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 26,
"labelWidth": 61,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -112,20 +112,20 @@
"labelPercentage": 0,
"route": [
{
"x": 83,
"x": 53,
"y": 66
},
{
"x": 53,
"y": 106
},
{
"x": 53,
"y": 126
},
{
"x": 83,
"x": 53,
"y": 166
},
{
"x": 83,
"y": 186
},
{
"x": 83,
"y": 226
}
],
"isCurve": true,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="366" height="552" viewBox="-100 -100 366 552"><style type="text/css">
width="306" height="432" viewBox="-100 -100 306 432"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,8 +39,8 @@ width="366" height="552" viewBox="-100 -100 366 552"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="A"><g class="shape" ><rect x="13" y="0" width="140" height="126" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="83.000000" y="66.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">hello</text></g><g id="B"><g class="shape" ><rect x="0" y="226" width="166" height="126" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="83.000000" y="292.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">goodbye</text></g><g id="(A -&gt; B)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 83.000000 127.000000 C 83.000000 166.000000 83.000000 186.000000 83.000000 223.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#3673457740)"/></g><mask id="3673457740" maskUnits="userSpaceOnUse" x="-100" y="-100" width="366" height="552">
<rect x="-100" y="-100" width="366" height="552" fill="white"></rect>
]]></script><g id="A"><g class="shape" ><rect x="13" y="0" width="80" height="66" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="53.000000" y="38.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">hello</text></g><g id="B"><g class="shape" ><rect x="0" y="166" width="106" height="66" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="53.000000" y="204.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">goodbye</text></g><g id="(A -&gt; B)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 53.000000 67.000000 C 53.000000 106.000000 53.000000 126.000000 53.000000 163.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#584752433)"/></g><mask id="584752433" maskUnits="userSpaceOnUse" x="-100" y="-100" width="306" height="432">
<rect x="-100" y="-100" width="306" height="432" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text-bold {

Before

Width:  |  Height:  |  Size: 325 KiB

After

Width:  |  Height:  |  Size: 325 KiB

View file

@ -9,8 +9,8 @@
"x": 25,
"y": 12
},
"width": 140,
"height": 126,
"width": 80,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -37,8 +37,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 40,
"labelHeight": 26,
"labelWidth": 35,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -48,10 +48,10 @@
"type": "sequence_diagram",
"pos": {
"x": 12,
"y": 238
"y": 178
},
"width": 166,
"height": 126,
"width": 106,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -78,8 +78,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 26,
"labelWidth": 61,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -112,12 +112,12 @@
"labelPercentage": 0,
"route": [
{
"x": 95,
"y": 138
"x": 65,
"y": 78
},
{
"x": 95,
"y": 238
"x": 65,
"y": 178
}
],
"animated": false,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="366" height="552" viewBox="-88 -88 366 552"><style type="text/css">
width="306" height="432" viewBox="-88 -88 306 432"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -39,8 +39,8 @@ width="366" height="552" viewBox="-88 -88 366 552"><style type="text/css">
svgEl.setAttribute("height", height * ratio - 16);
}
});
]]></script><g id="A"><g class="shape" ><rect x="25" y="12" width="140" height="126" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="95.000000" y="78.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">hello</text></g><g id="B"><g class="shape" ><rect x="12" y="238" width="166" height="126" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="95.000000" y="304.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">goodbye</text></g><g id="(A -&gt; B)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 95.000000 139.000000 L 95.000000 235.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#3245083993)"/></g><mask id="3245083993" maskUnits="userSpaceOnUse" x="-100" y="-100" width="366" height="552">
<rect x="-100" y="-100" width="366" height="552" fill="white"></rect>
]]></script><g id="A"><g class="shape" ><rect x="25" y="12" width="80" height="66" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="65.000000" y="50.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">hello</text></g><g id="B"><g class="shape" ><rect x="12" y="178" width="106" height="66" style="fill:#FFFFFF;stroke:#0D32B2;stroke-width:0;" /></g><text class="text-bold" x="65.000000" y="216.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">goodbye</text></g><g id="(A -&gt; B)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 65.000000 79.000000 L 65.000000 175.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2561647952)"/></g><mask id="2561647952" maskUnits="userSpaceOnUse" x="-100" y="-100" width="306" height="432">
<rect x="-100" y="-100" width="306" height="432" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text-bold {

Before

Width:  |  Height:  |  Size: 325 KiB

After

Width:  |  Height:  |  Size: 325 KiB

View file

@ -6,8 +6,8 @@
"id": "md",
"type": "text",
"pos": {
"x": 9,
"y": 226
"x": 0,
"y": 166
},
"width": 95,
"height": 115,
@ -44,13 +44,13 @@
},
{
"id": "a",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"x": 21,
"y": 0
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -77,21 +77,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "",
"type": "rectangle",
"pos": {
"x": 0,
"y": 441
"x": 21,
"y": 381
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -118,8 +118,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -152,20 +152,20 @@
"labelPercentage": 0,
"route": [
{
"x": 56.5,
"x": 47.5,
"y": 66
},
{
"x": 47.5,
"y": 106
},
{
"x": 47.5,
"y": 126
},
{
"x": 56.5,
"x": 47.5,
"y": 166
},
{
"x": 56.5,
"y": 186
},
{
"x": 56.5,
"y": 226
}
],
"isCurve": true,
@ -200,20 +200,20 @@
"labelPercentage": 0,
"route": [
{
"x": 56.5,
"x": 47.5,
"y": 281
},
{
"x": 47.5,
"y": 321
},
{
"x": 47.5,
"y": 341
},
{
"x": 56.5,
"x": 47.5,
"y": 381
},
{
"x": 56.5,
"y": 401
},
{
"x": 56.5,
"y": 441
}
],
"isCurve": true,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="317" height="771" viewBox="-102 -102 317 771"><style type="text/css">
width="299" height="651" viewBox="-102 -102 299 651"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -796,7 +796,7 @@ width="317" height="771" viewBox="-102 -102 317 771"><style type="text/css">
.md .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em 0.25em 0.2em;
}
</style><g id="md"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="9.000000" y="226.000000" width="95" height="115"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><h1>hey</h1>
</style><g id="md"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="0.000000" y="166.000000" width="95" height="115"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><h1>hey</h1>
<ul>
<li>they
<ol>
@ -804,8 +804,8 @@ width="317" height="771" viewBox="-102 -102 317 771"><style type="text/css">
</ol>
</li>
</ul>
</div></foreignObject></g></g><g id="a"><g class="shape" ><rect x="0" y="0" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="56.500000" y="66.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="b"><g class="shape" ><rect x="0" y="441" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="56.500000" y="507.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="(a -&gt; md)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 56.500000 128.000000 C 56.500000 166.000000 56.500000 186.000000 56.500000 222.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2837502795)"/></g><g id="(md -&gt; b)[0]"><path d="M 56.500000 343.000000 C 56.500000 381.000000 56.500000 401.000000 56.500000 437.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2837502795)"/></g><mask id="2837502795" maskUnits="userSpaceOnUse" x="-100" y="-100" width="317" height="771">
<rect x="-100" y="-100" width="317" height="771" fill="white"></rect>
</div></foreignObject></g></g><g id="a"><g class="shape" ><rect x="21" y="0" width="53" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="47.500000" y="38.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="b"><g class="shape" ><rect x="21" y="381" width="53" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="47.500000" y="419.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="(a -&gt; md)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 47.500000 68.000000 C 47.500000 106.000000 47.500000 126.000000 47.500000 162.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#817120199)"/></g><g id="(md -&gt; b)[0]"><path d="M 47.500000 283.000000 C 47.500000 321.000000 47.500000 341.000000 47.500000 377.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#817120199)"/></g><mask id="817120199" maskUnits="userSpaceOnUse" x="-100" y="-100" width="299" height="651">
<rect x="-100" y="-100" width="299" height="651" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text {

Before

Width:  |  Height:  |  Size: 661 KiB

After

Width:  |  Height:  |  Size: 661 KiB

View file

@ -6,8 +6,8 @@
"id": "md",
"type": "text",
"pos": {
"x": 21,
"y": 238
"x": 12,
"y": 178
},
"width": 95,
"height": 115,
@ -44,13 +44,13 @@
},
{
"id": "a",
"type": "",
"type": "rectangle",
"pos": {
"x": 12,
"x": 33,
"y": 12
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -77,21 +77,21 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "",
"type": "rectangle",
"pos": {
"x": 12,
"y": 453
"x": 33,
"y": 393
},
"width": 113,
"height": 126,
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -118,8 +118,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
@ -152,12 +152,12 @@
"labelPercentage": 0,
"route": [
{
"x": 68.5,
"y": 138
"x": 59.5,
"y": 78
},
{
"x": 68.5,
"y": 238
"x": 59.5,
"y": 178
}
],
"animated": false,
@ -191,12 +191,12 @@
"labelPercentage": 0,
"route": [
{
"x": 68.5,
"y": 353
"x": 59.5,
"y": 293
},
{
"x": 68.5,
"y": 453
"x": 59.5,
"y": 393
}
],
"animated": false,

View file

@ -3,7 +3,7 @@
id="d2-svg"
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="317" height="771" viewBox="-90 -90 317 771"><style type="text/css">
width="299" height="651" viewBox="-90 -90 299 651"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -796,7 +796,7 @@ width="317" height="771" viewBox="-90 -90 317 771"><style type="text/css">
.md .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em 0.25em 0.2em;
}
</style><g id="md"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="21.000000" y="238.000000" width="95" height="115"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><h1>hey</h1>
</style><g id="md"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="12.000000" y="178.000000" width="95" height="115"><div xmlns="http://www.w3.org/1999/xhtml" class="md" style="background-color:transparent;color:#0A0F25;"><h1>hey</h1>
<ul>
<li>they
<ol>
@ -804,8 +804,8 @@ width="317" height="771" viewBox="-90 -90 317 771"><style type="text/css">
</ol>
</li>
</ul>
</div></foreignObject></g></g><g id="a"><g class="shape" ><rect x="12" y="12" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="68.500000" y="78.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="b"><g class="shape" ><rect x="12" y="453" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="68.500000" y="519.000000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="(a -&gt; md)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 68.500000 140.000000 L 68.500000 234.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2378193313)"/></g><g id="(md -&gt; b)[0]"><path d="M 68.500000 355.000000 L 68.500000 449.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#2378193313)"/></g><mask id="2378193313" maskUnits="userSpaceOnUse" x="-100" y="-100" width="317" height="771">
<rect x="-100" y="-100" width="317" height="771" fill="white"></rect>
</div></foreignObject></g></g><g id="a"><g class="shape" ><rect x="33" y="12" width="53" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="59.500000" y="50.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">a</text></g><g id="b"><g class="shape" ><rect x="33" y="393" width="53" height="66" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g><text class="text-bold" x="59.500000" y="431.500000" style="text-anchor:middle;font-size:16px;fill:#0A0F25">b</text></g><g id="(a -&gt; md)[0]"><marker id="mk-3990223579" 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 class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 59.500000 80.000000 L 59.500000 174.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#500331167)"/></g><g id="(md -&gt; b)[0]"><path d="M 59.500000 295.000000 L 59.500000 389.000000" class="connection" style="fill:none;stroke:#0D32B2;stroke-width:2;" marker-end="url(#mk-3990223579)" mask="url(#500331167)"/></g><mask id="500331167" maskUnits="userSpaceOnUse" x="-100" y="-100" width="299" height="651">
<rect x="-100" y="-100" width="299" height="651" fill="white"></rect>
</mask><style type="text/css"><![CDATA[
.text {

Before

Width:  |  Height:  |  Size: 660 KiB

After

Width:  |  Height:  |  Size: 660 KiB

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