From 5b22382cfd480dd15692e9468afa27bebbf3ffe1 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Fri, 31 Mar 2023 18:13:12 -0700 Subject: [PATCH 01/31] add teleport_grid test --- e2etests/stable_test.go | 1 + e2etests/testdata/files/teleport_grid.d2 | 72 + .../stable/teleport_grid/dagre/board.exp.json | 1888 +++++++++++++++++ .../stable/teleport_grid/dagre/sketch.exp.svg | 853 ++++++++ .../stable/teleport_grid/elk/board.exp.json | 1858 ++++++++++++++++ .../stable/teleport_grid/elk/sketch.exp.svg | 853 ++++++++ 6 files changed, 5525 insertions(+) create mode 100644 e2etests/testdata/files/teleport_grid.d2 create mode 100644 e2etests/testdata/stable/teleport_grid/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/teleport_grid/elk/board.exp.json create mode 100644 e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index 521d4c5e4..1fae58d41 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -2465,6 +2465,7 @@ scenarios: { }`, }, loadFromFile(t, "arrowhead_scaling"), + loadFromFile(t, "teleport_grid"), } runa(t, tcs) diff --git a/e2etests/testdata/files/teleport_grid.d2 b/e2etests/testdata/files/teleport_grid.d2 new file mode 100644 index 000000000..fc8e6476e --- /dev/null +++ b/e2etests/testdata/files/teleport_grid.d2 @@ -0,0 +1,72 @@ +direction: right + +users -- via -- teleport + +teleport -> jita: "all connections audited and logged" +teleport -> infra + +teleport -> identity provider +teleport <- identity provider + +users: "" { + rows: 2 + + Engineers: { + shape: circle + icon: https://icons.terrastruct.com/essentials%2F365-user.svg + } + Machines: { + shape: circle + icon: https://icons.terrastruct.com/aws%2FCompute%2FCompute.svg + } +} + +via: "" { + columns: 1 + + https: "HTTPS://" + kubectl: "> kubectl" + tsh: "> tsh" + api: "> api" + db clients: "DB Clients" +} + +teleport: "" { + rows: 2 + columns: 2 + + t: |md + # Teleport + | + inp: |md + # Identity Native Proxy + | + + Audit Log.icon: https://icons.terrastruct.com/tech%2Flaptop.svg + Cert Authority.icon: https://icons.terrastruct.com/azure%2FWeb%20Service%20Color%2FApp%20Service%20Certificates.svg +} + +jita: "Just-in-time Access via" { + rows: 1 + + Slack.icon: https://icons.terrastruct.com/dev%2Fslack.svg + Mattermost + Jira + Pagerduty + Email.icon: https://icons.terrastruct.com/aws%2F_General%2FAWS-Email_light-bg.svg +} + +infra: Infrastructure { + rows: 2 + + ssh.icon: https://icons.terrastruct.com/essentials%2F112-server.svg + Kubernetes.icon: https://icons.terrastruct.com/azure%2F_Companies%2FKubernetes.svg + My SQL.icon: https://icons.terrastruct.com/dev%2Fmysql.svg + MongoDB.icon: https://icons.terrastruct.com/dev%2Fmongodb.svg + PSQL.icon: https://icons.terrastruct.com/dev%2Fpostgresql.svg + Windows.icon: https://icons.terrastruct.com/dev%2Fwindows.svg +} + +identity provider: Indentity Provider { + icon: https://icons.terrastruct.com/azure%2FIdentity%20Service%20Color%2FIdentity%20governance.svg +} diff --git a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json new file mode 100644 index 000000000..66435abc2 --- /dev/null +++ b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json @@ -0,0 +1,1888 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "users", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 423, + "height": 540, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + }, + { + "id": "via", + "type": "rectangle", + "pos": { + "x": 694, + "y": 290 + }, + "width": 472, + "height": 625, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + }, + { + "id": "teleport", + "type": "rectangle", + "pos": { + "x": 1437, + "y": 564 + }, + "width": 573, + "height": 1231, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + }, + { + "id": "jita", + "type": "rectangle", + "pos": { + "x": 2512, + "y": 844 + }, + "width": 423, + "height": 688, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Just-in-time Access via", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 266, + "labelHeight": 36, + "labelPosition": "OUTSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "infra", + "type": "rectangle", + "pos": { + "x": 2512, + "y": 1634 + }, + "width": 423, + "height": 982, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Infrastructure", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 160, + "labelHeight": 36, + "labelPosition": "OUTSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "identity provider", + "type": "rectangle", + "pos": { + "x": 830, + "y": 1261 + }, + "width": 201, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/azure/Identity Service Color/Identity governance.svg", + "RawPath": "/azure%2FIdentity%20Service%20Color%2FIdentity%20governance.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Indentity Provider", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 130, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "users.rows", + "type": "rectangle", + "pos": { + "x": 185, + "y": 41 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "users.Engineers", + "type": "oval", + "pos": { + "x": 136, + "y": 127 + }, + "width": 152, + "height": 178, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/essentials/365-user.svg", + "RawPath": "/essentials%2F365-user.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Engineers", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 69, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "users.Machines", + "type": "oval", + "pos": { + "x": 137, + "y": 325 + }, + "width": 149, + "height": 175, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/aws/Compute/Compute.svg", + "RawPath": "/aws%2FCompute%2FCompute.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Machines", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 66, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.columns", + "type": "rectangle", + "pos": { + "x": 904, + "y": 379 + }, + "width": 52, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "1", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 7, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.https", + "type": "rectangle", + "pos": { + "x": 877, + "y": 465 + }, + "width": 107, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "HTTPS://", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.kubectl", + "type": "rectangle", + "pos": { + "x": 875, + "y": 551 + }, + "width": 111, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "> kubectl", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 66, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.tsh", + "type": "rectangle", + "pos": { + "x": 891, + "y": 637 + }, + "width": 79, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "> tsh", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 34, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.api", + "type": "rectangle", + "pos": { + "x": 891, + "y": 723 + }, + "width": 79, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "> api", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 34, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.db clients", + "type": "rectangle", + "pos": { + "x": 872, + "y": 809 + }, + "width": 116, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "DB Clients", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 71, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.rows", + "type": "rectangle", + "pos": { + "x": 1697, + "y": 809 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.columns", + "type": "rectangle", + "pos": { + "x": 1697, + "y": 895 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.t", + "type": "text", + "pos": { + "x": 1663, + "y": 981 + }, + "width": 122, + "height": 51, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "transparent", + "stroke": "N1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "# Teleport", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "markdown", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 122, + "labelHeight": 51, + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.inp", + "type": "text", + "pos": { + "x": 1573, + "y": 1052 + }, + "width": 302, + "height": 51, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "transparent", + "stroke": "N1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "# Identity Native Proxy", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "markdown", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 302, + "labelHeight": 51, + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.Audit Log", + "type": "rectangle", + "pos": { + "x": 1654, + "y": 1123 + }, + "width": 140, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/tech/laptop.svg", + "RawPath": "/tech%2Flaptop.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Audit Log", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 69, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.Cert Authority", + "type": "rectangle", + "pos": { + "x": 1637, + "y": 1261 + }, + "width": 173, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/azure/Web Service Color/App Service Certificates.svg", + "RawPath": "/azure%2FWeb%20Service%20Color%2FApp%20Service%20Certificates.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Cert Authority", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 102, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.rows", + "type": "rectangle", + "pos": { + "x": 2698, + "y": 912 + }, + "width": 52, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "1", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 7, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Slack", + "type": "rectangle", + "pos": { + "x": 2669, + "y": 998 + }, + "width": 110, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/slack.svg", + "RawPath": "/dev%2Fslack.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Slack", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 39, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Mattermost", + "type": "rectangle", + "pos": { + "x": 2660, + "y": 1136 + }, + "width": 128, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Mattermost", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 83, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Jira", + "type": "rectangle", + "pos": { + "x": 2688, + "y": 1222 + }, + "width": 72, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Jira", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 27, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Pagerduty", + "type": "rectangle", + "pos": { + "x": 2664, + "y": 1308 + }, + "width": 119, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Pagerduty", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 74, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Email", + "type": "rectangle", + "pos": { + "x": 2668, + "y": 1394 + }, + "width": 111, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/aws/_General/AWS-Email_light-bg.svg", + "RawPath": "/aws%2F_General%2FAWS-Email_light-bg.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Email", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 40, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.rows", + "type": "rectangle", + "pos": { + "x": 2697, + "y": 1702 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.ssh", + "type": "rectangle", + "pos": { + "x": 2676, + "y": 1788 + }, + "width": 95, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/essentials/112-server.svg", + "RawPath": "/essentials%2F112-server.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ssh", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 24, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.Kubernetes", + "type": "rectangle", + "pos": { + "x": 2648, + "y": 1926 + }, + "width": 152, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/azure/_Companies/Kubernetes.svg", + "RawPath": "/azure%2F_Companies%2FKubernetes.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Kubernetes", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 81, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.My SQL", + "type": "rectangle", + "pos": { + "x": 2663, + "y": 2064 + }, + "width": 122, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/mysql.svg", + "RawPath": "/dev%2Fmysql.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "My SQL", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 51, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.MongoDB", + "type": "rectangle", + "pos": { + "x": 2655, + "y": 2202 + }, + "width": 138, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/mongodb.svg", + "RawPath": "/dev%2Fmongodb.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "MongoDB", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 67, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.PSQL", + "type": "rectangle", + "pos": { + "x": 2670, + "y": 2340 + }, + "width": 108, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/postgresql.svg", + "RawPath": "/dev%2Fpostgresql.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "PSQL", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 37, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.Windows", + "type": "rectangle", + "pos": { + "x": 2656, + "y": 2478 + }, + "width": 136, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/windows.svg", + "RawPath": "/dev%2Fwindows.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Windows", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 65, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [ + { + "id": "(users -- via)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "via", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 423, + "y": 412 + }, + { + "x": 531.4, + "y": 412 + }, + { + "x": 585.7, + "y": 412 + }, + { + "x": 694.5, + "y": 412 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(via -- teleport)[0]", + "src": "via", + "srcArrow": "none", + "srcLabel": "", + "dst": "teleport", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1166, + "y": 842 + }, + { + "x": 1274.4, + "y": 842 + }, + { + "x": 1328.7, + "y": 842 + }, + { + "x": 1437.5, + "y": 842 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport -> jita)[0]", + "src": "teleport", + "srcArrow": "none", + "srcLabel": "", + "dst": "jita", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "all connections audited and logged", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 231, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 2010, + "y": 924.75 + }, + { + "x": 2210.8, + "y": 924.75 + }, + { + "x": 2311.2, + "y": 924.75 + }, + { + "x": 2512, + "y": 924.75 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport -> infra)[0]", + "src": "teleport", + "srcArrow": "none", + "srcLabel": "", + "dst": "infra", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 2010, + "y": 1715.25 + }, + { + "x": 2210.8, + "y": 1715.25 + }, + { + "x": 2311.2, + "y": 1715.25 + }, + { + "x": 2512, + "y": 1715.25 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport -> identity provider)[0]", + "src": "teleport", + "srcArrow": "none", + "srcLabel": "", + "dst": "identity provider", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1437, + "y": 1715.25 + }, + { + "x": 1328.6, + "y": 1715.25 + }, + { + "x": 1125.8, + "y": 1648.05 + }, + { + "x": 965, + "y": 1379.25 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport <- identity provider)[0]", + "src": "teleport", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "identity provider", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1437, + "y": 1148.25 + }, + { + "x": 1328.6, + "y": 1148.25 + }, + { + "x": 1135, + "y": 1170.85 + }, + { + "x": 1011, + "y": 1261.25 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg new file mode 100644 index 000000000..5bc6ca42e --- /dev/null +++ b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg @@ -0,0 +1,853 @@ +Just-in-time Access viaInfrastructureIndentity Provider2EngineersMachines1HTTPS://> kubectl> tsh> apiDB Clients22

Teleport

+

Identity Native Proxy

+
Audit LogCert Authority1SlackMattermostJiraPagerdutyEmail2sshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + + +
\ No newline at end of file diff --git a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json new file mode 100644 index 000000000..d9d10a15d --- /dev/null +++ b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json @@ -0,0 +1,1858 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "users", + "type": "rectangle", + "pos": { + "x": 12, + "y": 842 + }, + "width": 252, + "height": 559, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + }, + { + "id": "via", + "type": "rectangle", + "pos": { + "x": 334, + "y": 823 + }, + "width": 216, + "height": 596, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + }, + { + "id": "teleport", + "type": "rectangle", + "pos": { + "x": 620, + "y": 786 + }, + "width": 402, + "height": 670, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + }, + { + "id": "jita", + "type": "rectangle", + "pos": { + "x": 1474, + "y": 12 + }, + "width": 311, + "height": 700, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Just-in-time Access via", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 266, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "infra", + "type": "rectangle", + "pos": { + "x": 1152, + "y": 394 + }, + "width": 252, + "height": 994, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Infrastructure", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 160, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "identity provider", + "type": "rectangle", + "pos": { + "x": 1152, + "y": 1408 + }, + "width": 201, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/azure/Identity Service Color/Identity governance.svg", + "RawPath": "/azure%2FIdentity%20Service%20Color%2FIdentity%20governance.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Indentity Provider", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 130, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "users.rows", + "type": "rectangle", + "pos": { + "x": 111, + "y": 892 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "users.Engineers", + "type": "oval", + "pos": { + "x": 62, + "y": 978 + }, + "width": 152, + "height": 178, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/essentials/365-user.svg", + "RawPath": "/essentials%2F365-user.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Engineers", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 69, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "users.Machines", + "type": "oval", + "pos": { + "x": 63, + "y": 1176 + }, + "width": 149, + "height": 175, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/aws/Compute/Compute.svg", + "RawPath": "/aws%2FCompute%2FCompute.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Machines", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 66, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.columns", + "type": "rectangle", + "pos": { + "x": 416, + "y": 873 + }, + "width": 52, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "1", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 7, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.https", + "type": "rectangle", + "pos": { + "x": 388, + "y": 959 + }, + "width": 107, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "HTTPS://", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.kubectl", + "type": "rectangle", + "pos": { + "x": 386, + "y": 1045 + }, + "width": 111, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "> kubectl", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 66, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.tsh", + "type": "rectangle", + "pos": { + "x": 402, + "y": 1131 + }, + "width": 79, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "> tsh", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 34, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.api", + "type": "rectangle", + "pos": { + "x": 402, + "y": 1217 + }, + "width": 79, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "> api", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 34, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "via.db clients", + "type": "rectangle", + "pos": { + "x": 384, + "y": 1303 + }, + "width": 116, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "DB Clients", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 71, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.rows", + "type": "rectangle", + "pos": { + "x": 794, + "y": 836 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.columns", + "type": "rectangle", + "pos": { + "x": 794, + "y": 922 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.t", + "type": "text", + "pos": { + "x": 760, + "y": 1008 + }, + "width": 122, + "height": 51, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "transparent", + "stroke": "N1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "# Teleport", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "markdown", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 122, + "labelHeight": 51, + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.inp", + "type": "text", + "pos": { + "x": 670, + "y": 1079 + }, + "width": 302, + "height": 51, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "transparent", + "stroke": "N1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "# Identity Native Proxy", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "markdown", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 302, + "labelHeight": 51, + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.Audit Log", + "type": "rectangle", + "pos": { + "x": 751, + "y": 1150 + }, + "width": 140, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/tech/laptop.svg", + "RawPath": "/tech%2Flaptop.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Audit Log", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 69, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "teleport.Cert Authority", + "type": "rectangle", + "pos": { + "x": 734, + "y": 1288 + }, + "width": 173, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/azure/Web Service Color/App Service Certificates.svg", + "RawPath": "/azure%2FWeb%20Service%20Color%2FApp%20Service%20Certificates.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Cert Authority", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 102, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.rows", + "type": "rectangle", + "pos": { + "x": 1603, + "y": 62 + }, + "width": 52, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "1", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 7, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Slack", + "type": "rectangle", + "pos": { + "x": 1574, + "y": 148 + }, + "width": 110, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/slack.svg", + "RawPath": "/dev%2Fslack.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Slack", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 39, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Mattermost", + "type": "rectangle", + "pos": { + "x": 1565, + "y": 286 + }, + "width": 128, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Mattermost", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 83, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Jira", + "type": "rectangle", + "pos": { + "x": 1593, + "y": 372 + }, + "width": 72, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Jira", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 27, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Pagerduty", + "type": "rectangle", + "pos": { + "x": 1570, + "y": 458 + }, + "width": 119, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Pagerduty", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 74, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "jita.Email", + "type": "rectangle", + "pos": { + "x": 1574, + "y": 544 + }, + "width": 111, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/aws/_General/AWS-Email_light-bg.svg", + "RawPath": "/aws%2F_General%2FAWS-Email_light-bg.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Email", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 40, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.rows", + "type": "rectangle", + "pos": { + "x": 1251, + "y": 444 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "2", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.ssh", + "type": "rectangle", + "pos": { + "x": 1230, + "y": 530 + }, + "width": 95, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/essentials/112-server.svg", + "RawPath": "/essentials%2F112-server.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ssh", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 24, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.Kubernetes", + "type": "rectangle", + "pos": { + "x": 1202, + "y": 668 + }, + "width": 152, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/azure/_Companies/Kubernetes.svg", + "RawPath": "/azure%2F_Companies%2FKubernetes.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Kubernetes", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 81, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.My SQL", + "type": "rectangle", + "pos": { + "x": 1217, + "y": 806 + }, + "width": 122, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/mysql.svg", + "RawPath": "/dev%2Fmysql.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "My SQL", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 51, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.MongoDB", + "type": "rectangle", + "pos": { + "x": 1209, + "y": 944 + }, + "width": 138, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/mongodb.svg", + "RawPath": "/dev%2Fmongodb.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "MongoDB", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 67, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.PSQL", + "type": "rectangle", + "pos": { + "x": 1224, + "y": 1082 + }, + "width": 108, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/postgresql.svg", + "RawPath": "/dev%2Fpostgresql.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "PSQL", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 37, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "infra.Windows", + "type": "rectangle", + "pos": { + "x": 1210, + "y": 1220 + }, + "width": 136, + "height": 118, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/windows.svg", + "RawPath": "/dev%2Fwindows.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Windows", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 65, + "labelHeight": 21, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [ + { + "id": "(users -- via)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "via", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 264, + "y": 1121.8333333333333 + }, + { + "x": 334, + "y": 1121.8333333333333 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(via -- teleport)[0]", + "src": "via", + "srcArrow": "none", + "srcLabel": "", + "dst": "teleport", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 550, + "y": 1121.8333333333333 + }, + { + "x": 620, + "y": 1121.8333333333333 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport -> jita)[0]", + "src": "teleport", + "srcArrow": "none", + "srcLabel": "", + "dst": "jita", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "all connections audited and logged", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 231, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 1022, + "y": 920.8333333333333 + }, + { + "x": 1062, + "y": 920.8333333333333 + }, + { + "x": 1062, + "y": 362 + }, + { + "x": 1474, + "y": 362 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport -> infra)[0]", + "src": "teleport", + "srcArrow": "none", + "srcLabel": "", + "dst": "infra", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1022, + "y": 1054.8333333333333 + }, + { + "x": 1152, + "y": 1054.8333333333333 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport -> identity provider)[0]", + "src": "teleport", + "srcArrow": "none", + "srcLabel": "", + "dst": "identity provider", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1022, + "y": 1188.8333333333333 + }, + { + "x": 1112, + "y": 1188.8333333333333 + }, + { + "x": 1112, + "y": 1447.3333333333333 + }, + { + "x": 1152, + "y": 1447.3333333333333 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(teleport <- identity provider)[0]", + "src": "teleport", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "identity provider", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1022, + "y": 1322.8333333333333 + }, + { + "x": 1062, + "y": 1322.8333333333333 + }, + { + "x": 1062, + "y": 1486.6666666666667 + }, + { + "x": 1152, + "y": 1486.6666666666667 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg new file mode 100644 index 000000000..d0f70137b --- /dev/null +++ b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg @@ -0,0 +1,853 @@ +Just-in-time Access viaInfrastructureIndentity Provider2EngineersMachines1HTTPS://> kubectl> tsh> apiDB Clients22

Teleport

+

Identity Native Proxy

+
Audit LogCert Authority1SlackMattermostJiraPagerdutyEmail2sshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + + +
\ No newline at end of file From d139eeadadeadaa9d72cf97cfa5f3a5cf895e4d7 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Fri, 31 Mar 2023 17:18:17 -0700 Subject: [PATCH 02/31] layout with grids --- d2compiler/compile.go | 26 ++ d2compiler/compile_test.go | 20 ++ d2exporter/export_test.go | 3 +- d2graph/d2graph.go | 8 + d2graph/grid.go | 6 + d2layouts/d2grid/layout.go | 223 ++++++++++++++++++ d2layouts/d2sequence/layout.go | 2 +- d2lib/d2.go | 7 +- d2oracle/edit.go | 10 + testdata/d2compiler/TestCompile/grid.exp.json | 180 ++++++++++++++ .../TestCompile/grid_negative.exp.json | 12 + 11 files changed, 493 insertions(+), 4 deletions(-) create mode 100644 d2graph/grid.go create mode 100644 d2layouts/d2grid/layout.go create mode 100644 testdata/d2compiler/TestCompile/grid.exp.json create mode 100644 testdata/d2compiler/TestCompile/grid_negative.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 28288795d..4dd2badbb 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -362,6 +362,32 @@ func (c *compiler) compileReserved(attrs *d2graph.Attributes, f *d2ir.Field) { } attrs.Constraint.Value = scalar.ScalarString() attrs.Constraint.MapKey = f.LastPrimaryKey() + case "rows": + v, err := strconv.Atoi(scalar.ScalarString()) + if err != nil { + c.errorf(scalar, "non-integer rows %#v: %s", scalar.ScalarString(), err) + return + } + if v < 0 { + c.errorf(scalar, "rows must be a non-negative integer: %#v", scalar.ScalarString()) + return + } + attrs.Rows = &d2graph.Scalar{} + attrs.Rows.Value = scalar.ScalarString() + attrs.Rows.MapKey = f.LastPrimaryKey() + case "columns": + v, err := strconv.Atoi(scalar.ScalarString()) + if err != nil { + c.errorf(scalar, "non-integer columns %#v: %s", scalar.ScalarString(), err) + return + } + if v < 0 { + c.errorf(scalar, "columns must be a non-negative integer: %#v", scalar.ScalarString()) + return + } + attrs.Columns = &d2graph.Scalar{} + attrs.Columns.Value = scalar.ScalarString() + attrs.Columns.MapKey = f.LastPrimaryKey() } if attrs.Link != nil && attrs.Tooltip != nil { diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 53e33e22f..7dc218cae 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2268,6 +2268,26 @@ obj { `, expErr: `d2/testdata/d2compiler/TestCompile/near_near_const.d2:7:8: near keys cannot be set to an object with a constant near key`, }, + { + name: "grid", + text: `hey: { + rows: 200 + columns: 230 +} +`, + assertions: func(t *testing.T, g *d2graph.Graph) { + tassert.Equal(t, "200", g.Objects[0].Attributes.Rows.Value) + }, + }, + { + name: "grid_negative", + text: `hey: { + rows: 200 + columns: -200 +} +`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a non-negative integer: "-200"`, + }, } for _, tc := range testCases { diff --git a/d2exporter/export_test.go b/d2exporter/export_test.go index effcc07a8..bc6f47010 100644 --- a/d2exporter/export_test.go +++ b/d2exporter/export_test.go @@ -16,6 +16,7 @@ import ( "oss.terrastruct.com/d2/d2compiler" "oss.terrastruct.com/d2/d2exporter" "oss.terrastruct.com/d2/d2layouts/d2dagrelayout" + "oss.terrastruct.com/d2/d2layouts/d2grid" "oss.terrastruct.com/d2/d2layouts/d2sequence" "oss.terrastruct.com/d2/d2target" "oss.terrastruct.com/d2/lib/geo" @@ -231,7 +232,7 @@ func run(t *testing.T, tc testCase) { err = g.SetDimensions(nil, ruler, nil) assert.JSON(t, nil, err) - err = d2sequence.Layout(ctx, g, d2dagrelayout.DefaultLayout) + err = d2sequence.Layout(ctx, g, d2grid.Layout(ctx, g, d2dagrelayout.DefaultLayout)) if err != nil { t.Fatal(err) } diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index a9c370620..42f42977a 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -1,6 +1,7 @@ package d2graph import ( + "context" "errors" "fmt" "math" @@ -67,6 +68,8 @@ func (g *Graph) RootBoard() *Graph { return g } +type LayoutGraph func(context.Context, *Graph) error + // TODO consider having different Scalar types // Right now we'll hold any types in Value and just convert, e.g. floats type Scalar struct { @@ -129,6 +132,9 @@ type Attributes struct { Direction Scalar `json:"direction"` Constraint Scalar `json:"constraint"` + + Rows *Scalar `json:"rows,omitempty"` + Columns *Scalar `json:"columns,omitempty"` } // TODO references at the root scope should have their Scope set to root graph AST @@ -1534,6 +1540,8 @@ var SimpleReservedKeywords = map[string]struct{}{ "direction": {}, "top": {}, "left": {}, + "rows": {}, + "columns": {}, } // ReservedKeywordHolders are reserved keywords that are meaningless on its own and exist solely to hold a set of reserved keywords diff --git a/d2graph/grid.go b/d2graph/grid.go new file mode 100644 index 000000000..b746f11a3 --- /dev/null +++ b/d2graph/grid.go @@ -0,0 +1,6 @@ +package d2graph + +func (obj *Object) IsGrid() bool { + return obj != nil && obj.Attributes != nil && len(obj.ChildrenArray) != 0 && + (obj.Attributes.Rows != nil || obj.Attributes.Columns != nil) +} diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go new file mode 100644 index 000000000..05f4176f2 --- /dev/null +++ b/d2layouts/d2grid/layout.go @@ -0,0 +1,223 @@ +package d2grid + +import ( + "context" + "math" + "sort" + "strconv" + + "oss.terrastruct.com/d2/d2graph" + "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/d2/lib/label" + "oss.terrastruct.com/util-go/go2" +) + +const CONTAINER_PADDING = 60. +const HORIZONTAL_PAD = 40. +const VERTICAL_PAD = 40. + +type grid struct { + root *d2graph.Object + nodes []*d2graph.Object + rows int + columns int + + width float64 + height float64 +} + +func newGrid(root *d2graph.Object) *grid { + g := grid{root: root, nodes: root.ChildrenArray} + if root.Attributes.Rows != nil { + g.rows, _ = strconv.Atoi(root.Attributes.Rows.Value) + } + if root.Attributes.Columns != nil { + g.columns, _ = strconv.Atoi(root.Attributes.Columns.Value) + } + + // compute exact row/column count based on values entered + // TODO consider making this based on node dimensions + if g.rows == 0 { + // set rows based on number of columns + if g.columns == 0 { + // 0,0: put everything in one row + g.rows = 1 + g.columns = len(g.nodes) + } else { + g.rows = len(g.nodes) / g.columns + if len(g.nodes)%g.columns != 0 { + g.rows++ + } + } + } else if g.columns == 0 { + // set columns based on number of rows + g.columns = len(g.nodes) / g.rows + if len(g.nodes)%g.rows != 0 { + g.columns++ + } + } else { + // rows and columns specified (add more rows if needed) + capacity := g.rows * g.columns + for capacity < len(g.nodes) { + g.rows++ + capacity += g.columns + } + } + + return &g +} + +func (g *grid) shift(dx, dy float64) { + for _, obj := range g.nodes { + obj.TopLeft.X += dx + obj.TopLeft.Y += dy + } +} + +// Layout runs the grid layout on containers with rows/columns +// Note: children are not allowed edges or descendants +// +// 1. Traverse graph from root, skip objects with no rows/columns +// 2. Construct a grid with the container children +// 3. Remove the children from the main graph +// 4. Run grid layout +// 5. Set the resulting dimensions to the main graph shape +// 6. Run core layouts (without grid children) +// 7. Put grid children back in correct location +func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d2graph.LayoutGraph { + return func(ctx context.Context, g *d2graph.Graph) error { + grids, objectOrder, err := withoutGrids(ctx, g) + if err != nil { + return err + } + + if g.Root.IsGrid() { + g.Root.TopLeft = geo.NewPoint(0, 0) + } else if err := layout(ctx, g); err != nil { + return err + } + + cleanup(g, grids, objectOrder) + return nil + } +} + +func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { + grid := newGrid(obj) + + // position nodes + cursor := geo.NewPoint(0, 0) + maxWidth := 0. + for i := 0; i < grid.rows; i++ { + maxHeight := 0. + for j := 0; j < grid.columns; j++ { + n := grid.nodes[i*grid.columns+j] + n.TopLeft = cursor.Copy() + cursor.X += n.Width + HORIZONTAL_PAD + maxHeight = math.Max(maxHeight, n.Height) + } + maxWidth = math.Max(maxWidth, cursor.X-HORIZONTAL_PAD) + cursor.X = 0 + cursor.Y += float64(maxHeight) + VERTICAL_PAD + } + grid.width = maxWidth + grid.height = cursor.Y - VERTICAL_PAD + + // position labels and icons + for _, n := range grid.nodes { + if n.Attributes.Icon != nil { + n.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) + n.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } else { + n.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } + } + + return grid, nil +} + +func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*grid, objectOrder map[string]int, err error) { + toRemove := make(map[*d2graph.Object]struct{}) + grids := make(map[string]*grid) + + if len(g.Objects) > 0 { + queue := make([]*d2graph.Object, 1, len(g.Objects)) + queue[0] = g.Root + for len(queue) > 0 { + obj := queue[0] + queue = queue[1:] + if len(obj.ChildrenArray) == 0 { + continue + } + if !obj.IsGrid() { + queue = append(queue, obj.ChildrenArray...) + continue + } + + grid, err := layoutGrid(g, obj) + if err != nil { + return nil, nil, err + } + obj.Children = make(map[string]*d2graph.Object) + obj.ChildrenArray = nil + obj.Box = geo.NewBox(nil, grid.width+CONTAINER_PADDING*2, grid.height+CONTAINER_PADDING*2) + obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) + grids[obj.AbsID()] = grid + + for _, node := range grid.nodes { + toRemove[node] = struct{}{} + } + } + } + + objectOrder = make(map[string]int) + layoutObjects := make([]*d2graph.Object, 0, len(toRemove)) + for i, obj := range g.Objects { + objectOrder[obj.AbsID()] = i + if _, exists := toRemove[obj]; !exists { + layoutObjects = append(layoutObjects, obj) + } + } + g.Objects = layoutObjects + + return grids, objectOrder, nil +} + +// cleanup restores the graph after the core layout engine finishes +// - translating the grid to its position placed by the core layout engine +// - restore the children of the grid +// - sorts objects to their original graph order +func cleanup(g *d2graph.Graph, grids map[string]*grid, objectsOrder map[string]int) { + var objects []*d2graph.Object + if g.Root.IsGrid() { + objects = []*d2graph.Object{g.Root} + } else { + objects = g.Objects + } + for _, obj := range objects { + if _, exists := grids[obj.AbsID()]; !exists { + continue + } + obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) + sd := grids[obj.AbsID()] + + // shift the grid from (0, 0) + sd.shift( + obj.TopLeft.X+CONTAINER_PADDING, + obj.TopLeft.Y+CONTAINER_PADDING, + ) + + obj.Children = make(map[string]*d2graph.Object) + obj.ChildrenArray = make([]*d2graph.Object, 0) + for _, child := range sd.nodes { + obj.Children[child.ID] = child + obj.ChildrenArray = append(obj.ChildrenArray, child) + } + + g.Objects = append(g.Objects, grids[obj.AbsID()].nodes...) + } + + sort.SliceStable(g.Objects, func(i, j int) bool { + return objectsOrder[g.Objects[i].AbsID()] < objectsOrder[g.Objects[j].AbsID()] + }) +} diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go index 28755f3e0..cfae446c4 100644 --- a/d2layouts/d2sequence/layout.go +++ b/d2layouts/d2sequence/layout.go @@ -78,7 +78,7 @@ func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string] // 5. Set the resulting dimensions to the main graph shape // 6. Run core layouts (still without sequence diagram innards) // 7. Put back sequence diagram innards in correct location -func Layout(ctx context.Context, g *d2graph.Graph, layout func(ctx context.Context, g *d2graph.Graph) error) error { +func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) error { sequenceDiagrams, objectOrder, edgeOrder, err := WithoutSequenceDiagrams(ctx, g) if err != nil { return err diff --git a/d2lib/d2.go b/d2lib/d2.go index 060204ea9..11638833a 100644 --- a/d2lib/d2.go +++ b/d2lib/d2.go @@ -10,6 +10,7 @@ import ( "oss.terrastruct.com/d2/d2exporter" "oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/d2layouts/d2dagrelayout" + "oss.terrastruct.com/d2/d2layouts/d2grid" "oss.terrastruct.com/d2/d2layouts/d2near" "oss.terrastruct.com/d2/d2layouts/d2sequence" "oss.terrastruct.com/d2/d2renderers/d2fonts" @@ -70,7 +71,9 @@ func compile(ctx context.Context, g *d2graph.Graph, opts *CompileOptions) (*d2ta constantNears := d2near.WithoutConstantNears(ctx, g) - err = d2sequence.Layout(ctx, g, coreLayout) + layoutWithGrids := d2grid.Layout(ctx, g, coreLayout) + + err = d2sequence.Layout(ctx, g, layoutWithGrids) if err != nil { return nil, err } @@ -110,7 +113,7 @@ func compile(ctx context.Context, g *d2graph.Graph, opts *CompileOptions) (*d2ta return d, nil } -func getLayout(opts *CompileOptions) (func(context.Context, *d2graph.Graph) error, error) { +func getLayout(opts *CompileOptions) (d2graph.LayoutGraph, error) { if opts.Layout != nil { return opts.Layout, nil } else if os.Getenv("D2_LAYOUT") == "dagre" { diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 668b6d4a0..376634e22 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -314,6 +314,16 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error { attrs.Left.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } + case "rows": + if attrs.Rows != nil && attrs.Rows.MapKey != nil { + attrs.Rows.MapKey.SetScalar(mk.Value.ScalarBox()) + return nil + } + case "columns": + if attrs.Columns != nil && attrs.Columns.MapKey != nil { + attrs.Columns.MapKey.SetScalar(mk.Value.ScalarBox()) + return nil + } case "source-arrowhead", "target-arrowhead": if reservedKey == "source-arrowhead" { attrs = edge.SrcArrowhead diff --git a/testdata/d2compiler/TestCompile/grid.exp.json b/testdata/d2compiler/TestCompile/grid.exp.json new file mode 100644 index 000000000..8cad38d75 --- /dev/null +++ b/testdata/d2compiler/TestCompile/grid.exp.json @@ -0,0 +1,180 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-4:0:34", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-3:1:33", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-0:3:3", + "value": [ + { + "string": "hey", + "raw_string": "hey" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:5:5-3:0:32", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:10:17", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:5:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:5:12", + "value": [ + { + "string": "rows", + "raw_string": "rows" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:7:14-1:10:17", + "raw": "200", + "value": "200" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:19-2:13:31", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:19-2:8:26", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:19-2:8:26", + "value": [ + { + "string": "columns", + "raw_string": "columns" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:10:28-2:13:31", + "raw": "230", + "value": "230" + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "hey", + "id_val": "hey", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-0:3:3", + "value": [ + { + "string": "hey", + "raw_string": "hey" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "hey" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + }, + "rows": { + "value": "200" + }, + "columns": { + "value": "230" + } + }, + "zIndex": 0 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile/grid_negative.exp.json b/testdata/d2compiler/TestCompile/grid_negative.exp.json new file mode 100644 index 000000000..ff17efc56 --- /dev/null +++ b/testdata/d2compiler/TestCompile/grid_negative.exp.json @@ -0,0 +1,12 @@ +{ + "graph": null, + "err": { + "ioerr": null, + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/grid_negative.d2,2:10:28-2:14:32", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a non-negative integer: \"-200\"" + } + ] + } +} From 67ca089a4b74cde48764c53d9eae2917d302019b Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Fri, 31 Mar 2023 18:49:15 -0700 Subject: [PATCH 03/31] update test --- .../stable/teleport_grid/dagre/board.exp.json | 505 +++++------------- .../stable/teleport_grid/dagre/sketch.exp.svg | 190 +++---- .../stable/teleport_grid/elk/board.exp.json | 475 ++++------------ .../stable/teleport_grid/elk/sketch.exp.svg | 190 +++---- 4 files changed, 439 insertions(+), 921 deletions(-) diff --git a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json index 66435abc2..3877af04c 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json @@ -8,10 +8,10 @@ "type": "rectangle", "pos": { "x": 0, - "y": 0 + "y": 204 }, - "width": 423, - "height": 540, + "width": 272, + "height": 461, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -40,6 +40,7 @@ "underline": false, "labelWidth": 0, "labelHeight": 0, + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -47,11 +48,11 @@ "id": "via", "type": "rectangle", "pos": { - "x": 694, - "y": 290 + "x": 543, + "y": 130 }, - "width": 472, - "height": 625, + "width": 236, + "height": 610, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -80,6 +81,7 @@ "underline": false, "labelWidth": 0, "labelHeight": 0, + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -87,11 +89,11 @@ "id": "teleport", "type": "rectangle", "pos": { - "x": 1437, - "y": 564 + "x": 1050, + "y": 283 }, - "width": 573, - "height": 1231, + "width": 584, + "height": 303, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -120,6 +122,7 @@ "underline": false, "labelWidth": 0, "labelHeight": 0, + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -127,11 +130,11 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 2512, - "y": 844 + "x": 2136, + "y": 0 }, - "width": 423, - "height": 688, + "width": 820, + "height": 212, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -160,7 +163,7 @@ "underline": false, "labelWidth": 266, "labelHeight": 36, - "labelPosition": "OUTSIDE_TOP_CENTER", + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -168,11 +171,11 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 2512, - "y": 1634 + "x": 2255, + "y": 232 }, - "width": 423, - "height": 982, + "width": 582, + "height": 344, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -201,7 +204,7 @@ "underline": false, "labelWidth": 160, "labelHeight": 36, - "labelPosition": "OUTSIDE_TOP_CENTER", + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -209,8 +212,8 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 830, - "y": 1261 + "x": 2446, + "y": 596 }, "width": 201, "height": 118, @@ -258,56 +261,15 @@ "zIndex": 0, "level": 1 }, - { - "id": "users.rows", - "type": "rectangle", - "pos": { - "x": 185, - "y": 41 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "users.Engineers", "type": "oval", "pos": { - "x": 136, - "y": 127 + "x": 60, + "y": 264 }, "width": 152, - "height": 178, + "height": 152, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -356,11 +318,11 @@ "id": "users.Machines", "type": "oval", "pos": { - "x": 137, - "y": 325 + "x": 60, + "y": 456 }, "width": 149, - "height": 175, + "height": 149, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -405,53 +367,12 @@ "zIndex": 0, "level": 2 }, - { - "id": "via.columns", - "type": "rectangle", - "pos": { - "x": 904, - "y": 379 - }, - "width": 52, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "1", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 7, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "via.https", "type": "rectangle", "pos": { - "x": 877, - "y": 465 + "x": 603, + "y": 190 }, "width": 107, "height": 66, @@ -491,8 +412,8 @@ "id": "via.kubectl", "type": "rectangle", "pos": { - "x": 875, - "y": 551 + "x": 603, + "y": 296 }, "width": 111, "height": 66, @@ -532,8 +453,8 @@ "id": "via.tsh", "type": "rectangle", "pos": { - "x": 891, - "y": 637 + "x": 603, + "y": 402 }, "width": 79, "height": 66, @@ -573,8 +494,8 @@ "id": "via.api", "type": "rectangle", "pos": { - "x": 891, - "y": 723 + "x": 603, + "y": 508 }, "width": 79, "height": 66, @@ -614,8 +535,8 @@ "id": "via.db clients", "type": "rectangle", "pos": { - "x": 872, - "y": 809 + "x": 603, + "y": 614 }, "width": 116, "height": 66, @@ -651,94 +572,12 @@ "zIndex": 0, "level": 2 }, - { - "id": "teleport.rows", - "type": "rectangle", - "pos": { - "x": 1697, - "y": 809 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "teleport.columns", - "type": "rectangle", - "pos": { - "x": 1697, - "y": 895 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "teleport.t", "type": "text", "pos": { - "x": 1663, - "y": 981 + "x": 1110, + "y": 343 }, "width": 122, "height": 51, @@ -770,6 +609,7 @@ "underline": false, "labelWidth": 122, "labelHeight": 51, + "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, "level": 2 }, @@ -777,8 +617,8 @@ "id": "teleport.inp", "type": "text", "pos": { - "x": 1573, - "y": 1052 + "x": 1272, + "y": 343 }, "width": 302, "height": 51, @@ -810,6 +650,7 @@ "underline": false, "labelWidth": 302, "labelHeight": 51, + "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, "level": 2 }, @@ -817,11 +658,11 @@ "id": "teleport.Audit Log", "type": "rectangle", "pos": { - "x": 1654, - "y": 1123 + "x": 1110, + "y": 434 }, "width": 140, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -870,11 +711,11 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 1637, - "y": 1261 + "x": 1290, + "y": 434 }, "width": 173, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -919,56 +760,15 @@ "zIndex": 0, "level": 2 }, - { - "id": "jita.rows", - "type": "rectangle", - "pos": { - "x": 2698, - "y": 912 - }, - "width": 52, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "1", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 7, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 2669, - "y": 998 + "x": 2196, + "y": 60 }, "width": 110, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1017,8 +817,8 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 2660, - "y": 1136 + "x": 2346, + "y": 60 }, "width": 128, "height": 66, @@ -1058,8 +858,8 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 2688, - "y": 1222 + "x": 2514, + "y": 60 }, "width": 72, "height": 66, @@ -1099,8 +899,8 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 2664, - "y": 1308 + "x": 2626, + "y": 60 }, "width": 119, "height": 66, @@ -1140,11 +940,11 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 2668, - "y": 1394 + "x": 2785, + "y": 60 }, "width": 111, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1189,56 +989,15 @@ "zIndex": 0, "level": 2 }, - { - "id": "infra.rows", - "type": "rectangle", - "pos": { - "x": 2697, - "y": 1702 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 2676, - "y": 1788 + "x": 2315, + "y": 292 }, "width": 95, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1287,11 +1046,11 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 2648, - "y": 1926 + "x": 2450, + "y": 292 }, "width": 152, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1340,11 +1099,11 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 2663, - "y": 2064 + "x": 2642, + "y": 292 }, "width": 122, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1393,11 +1152,11 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 2655, - "y": 2202 + "x": 2315, + "y": 424 }, "width": 138, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1446,11 +1205,11 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 2670, - "y": 2340 + "x": 2493, + "y": 424 }, "width": 108, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1499,11 +1258,11 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 2656, - "y": 2478 + "x": 2641, + "y": 424 }, "width": 136, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1577,20 +1336,20 @@ "labelPercentage": 0, "route": [ { - "x": 423, - "y": 412 + "x": 272, + "y": 434.5 }, { - "x": 531.4, - "y": 412 + "x": 380.4, + "y": 434.5 }, { - "x": 585.7, - "y": 412 + "x": 434.7, + "y": 434.5 }, { - "x": 694.5, - "y": 412 + "x": 543.5, + "y": 434.5 } ], "isCurve": true, @@ -1626,20 +1385,20 @@ "labelPercentage": 0, "route": [ { - "x": 1166, - "y": 842 + "x": 779, + "y": 434.5 }, { - "x": 1274.4, - "y": 842 + "x": 887.4, + "y": 434.5 }, { - "x": 1328.7, - "y": 842 + "x": 941.7, + "y": 434.5 }, { - "x": 1437.5, - "y": 842 + "x": 1050.5, + "y": 434.5 } ], "isCurve": true, @@ -1675,20 +1434,20 @@ "labelPercentage": 0, "route": [ { - "x": 2010, - "y": 924.75 + "x": 1592.4246575342465, + "y": 283 }, { - "x": 2210.8, - "y": 924.75 + "x": 1826.4849315068493, + "y": 141.4 }, { - "x": 2311.2, - "y": 924.75 + "x": 1935.2, + "y": 106 }, { - "x": 2512, - "y": 924.75 + "x": 2136, + "y": 106 } ], "isCurve": true, @@ -1724,20 +1483,20 @@ "labelPercentage": 0, "route": [ { - "x": 2010, - "y": 1715.25 + "x": 1634, + "y": 418.0985267034991 }, { - "x": 2210.8, - "y": 1715.25 + "x": 1834.8, + "y": 406.81970534069984 }, { - "x": 2311.2, - "y": 1715.25 + "x": 1959, + "y": 404 }, { - "x": 2512, - "y": 1715.25 + "x": 2255, + "y": 404 } ], "isCurve": true, @@ -1773,20 +1532,20 @@ "labelPercentage": 0, "route": [ { - "x": 1437, - "y": 1715.25 + "x": 1634, + "y": 501.98802946593 }, { - "x": 1328.6, - "y": 1715.25 + "x": 1834.8, + "y": 548.397605893186 }, { - "x": 1125.8, - "y": 1648.05 + "x": 1997.1, + "y": 576.1111951588503 }, { - "x": 965, - "y": 1379.25 + "x": 2445.5, + "y": 640.5559757942511 } ], "isCurve": true, @@ -1822,20 +1581,20 @@ "labelPercentage": 0, "route": [ { - "x": 1437, - "y": 1148.25 + "x": 1634, + "y": 569.47605893186 }, { - "x": 1328.6, - "y": 1148.25 + "x": 1834.8, + "y": 662.295211786372 }, { - "x": 1135, - "y": 1170.85 + "x": 1997.1, + "y": 680.3274583963691 }, { - "x": 1011, - "y": 1261.25 + "x": 2445.5, + "y": 659.6372919818457 } ], "isCurve": true, diff --git a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg index 5bc6ca42e..6269083ef 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg @@ -1,24 +1,24 @@ -Just-in-time Access viaInfrastructureIndentity Provider2EngineersMachines1HTTPS://> kubectl> tsh> apiDB Clients22

Teleport

-

Identity Native Proxy

-
Audit LogCert Authority1SlackMattermostJiraPagerdutyEmail2sshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

+

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file diff --git a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json index d9d10a15d..0fad16a9e 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json @@ -8,10 +8,10 @@ "type": "rectangle", "pos": { "x": 12, - "y": 842 + "y": 196 }, - "width": 252, - "height": 559, + "width": 272, + "height": 461, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -40,6 +40,7 @@ "underline": false, "labelWidth": 0, "labelHeight": 0, + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -47,11 +48,11 @@ "id": "via", "type": "rectangle", "pos": { - "x": 334, - "y": 823 + "x": 354, + "y": 122 }, - "width": 216, - "height": 596, + "width": 236, + "height": 610, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -80,6 +81,7 @@ "underline": false, "labelWidth": 0, "labelHeight": 0, + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -87,11 +89,11 @@ "id": "teleport", "type": "rectangle", "pos": { - "x": 620, - "y": 786 + "x": 660, + "y": 275 }, - "width": 402, - "height": 670, + "width": 584, + "height": 303, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -120,6 +122,7 @@ "underline": false, "labelWidth": 0, "labelHeight": 0, + "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, @@ -127,11 +130,11 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 1474, + "x": 2026, "y": 12 }, - "width": 311, - "height": 700, + "width": 820, + "height": 212, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -168,11 +171,11 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 1152, - "y": 394 + "x": 1374, + "y": 150 }, - "width": 252, - "height": 994, + "width": 582, + "height": 344, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -209,8 +212,8 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 1152, - "y": 1408 + "x": 1374, + "y": 514 }, "width": 201, "height": 118, @@ -258,56 +261,15 @@ "zIndex": 0, "level": 1 }, - { - "id": "users.rows", - "type": "rectangle", - "pos": { - "x": 111, - "y": 892 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "users.Engineers", "type": "oval", "pos": { - "x": 62, - "y": 978 + "x": 72, + "y": 256 }, "width": 152, - "height": 178, + "height": 152, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -356,11 +318,11 @@ "id": "users.Machines", "type": "oval", "pos": { - "x": 63, - "y": 1176 + "x": 72, + "y": 448 }, "width": 149, - "height": 175, + "height": 149, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -405,53 +367,12 @@ "zIndex": 0, "level": 2 }, - { - "id": "via.columns", - "type": "rectangle", - "pos": { - "x": 416, - "y": 873 - }, - "width": 52, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "1", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 7, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "via.https", "type": "rectangle", "pos": { - "x": 388, - "y": 959 + "x": 414, + "y": 182 }, "width": 107, "height": 66, @@ -491,8 +412,8 @@ "id": "via.kubectl", "type": "rectangle", "pos": { - "x": 386, - "y": 1045 + "x": 414, + "y": 288 }, "width": 111, "height": 66, @@ -532,8 +453,8 @@ "id": "via.tsh", "type": "rectangle", "pos": { - "x": 402, - "y": 1131 + "x": 414, + "y": 394 }, "width": 79, "height": 66, @@ -573,8 +494,8 @@ "id": "via.api", "type": "rectangle", "pos": { - "x": 402, - "y": 1217 + "x": 414, + "y": 500 }, "width": 79, "height": 66, @@ -614,8 +535,8 @@ "id": "via.db clients", "type": "rectangle", "pos": { - "x": 384, - "y": 1303 + "x": 414, + "y": 606 }, "width": 116, "height": 66, @@ -651,94 +572,12 @@ "zIndex": 0, "level": 2 }, - { - "id": "teleport.rows", - "type": "rectangle", - "pos": { - "x": 794, - "y": 836 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "teleport.columns", - "type": "rectangle", - "pos": { - "x": 794, - "y": 922 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "teleport.t", "type": "text", "pos": { - "x": 760, - "y": 1008 + "x": 720, + "y": 335 }, "width": 122, "height": 51, @@ -770,6 +609,7 @@ "underline": false, "labelWidth": 122, "labelHeight": 51, + "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, "level": 2 }, @@ -777,8 +617,8 @@ "id": "teleport.inp", "type": "text", "pos": { - "x": 670, - "y": 1079 + "x": 882, + "y": 335 }, "width": 302, "height": 51, @@ -810,6 +650,7 @@ "underline": false, "labelWidth": 302, "labelHeight": 51, + "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, "level": 2 }, @@ -817,11 +658,11 @@ "id": "teleport.Audit Log", "type": "rectangle", "pos": { - "x": 751, - "y": 1150 + "x": 720, + "y": 426 }, "width": 140, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -870,11 +711,11 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 734, - "y": 1288 + "x": 900, + "y": 426 }, "width": 173, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -919,56 +760,15 @@ "zIndex": 0, "level": 2 }, - { - "id": "jita.rows", - "type": "rectangle", - "pos": { - "x": 1603, - "y": 62 - }, - "width": 52, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "1", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 7, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 1574, - "y": 148 + "x": 2086, + "y": 72 }, "width": 110, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1017,8 +817,8 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 1565, - "y": 286 + "x": 2236, + "y": 72 }, "width": 128, "height": 66, @@ -1058,8 +858,8 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 1593, - "y": 372 + "x": 2404, + "y": 72 }, "width": 72, "height": 66, @@ -1099,8 +899,8 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 1570, - "y": 458 + "x": 2516, + "y": 72 }, "width": 119, "height": 66, @@ -1140,11 +940,11 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 1574, - "y": 544 + "x": 2675, + "y": 72 }, "width": 111, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1189,56 +989,15 @@ "zIndex": 0, "level": 2 }, - { - "id": "infra.rows", - "type": "rectangle", - "pos": { - "x": 1251, - "y": 444 - }, - "width": 53, - "height": 66, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "2", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 8, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, { "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 1230, - "y": 530 + "x": 1434, + "y": 210 }, "width": 95, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1287,11 +1046,11 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 1202, - "y": 668 + "x": 1569, + "y": 210 }, "width": 152, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1340,11 +1099,11 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 1217, - "y": 806 + "x": 1761, + "y": 210 }, "width": 122, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1393,11 +1152,11 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 1209, - "y": 944 + "x": 1434, + "y": 342 }, "width": 138, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1446,11 +1205,11 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 1224, - "y": 1082 + "x": 1612, + "y": 342 }, "width": 108, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1499,11 +1258,11 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 1210, - "y": 1220 + "x": 1760, + "y": 342 }, "width": 136, - "height": 118, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -1577,12 +1336,12 @@ "labelPercentage": 0, "route": [ { - "x": 264, - "y": 1121.8333333333333 + "x": 284, + "y": 427.0333333333333 }, { - "x": 334, - "y": 1121.8333333333333 + "x": 354, + "y": 427.0333333333333 } ], "animated": false, @@ -1617,12 +1376,12 @@ "labelPercentage": 0, "route": [ { - "x": 550, - "y": 1121.8333333333333 + "x": 590, + "y": 427.0333333333333 }, { - "x": 620, - "y": 1121.8333333333333 + "x": 660, + "y": 427.0333333333333 } ], "animated": false, @@ -1657,20 +1416,20 @@ "labelPercentage": 0, "route": [ { - "x": 1022, - "y": 920.8333333333333 + "x": 1244, + "y": 336.1333333333333 }, { - "x": 1062, - "y": 920.8333333333333 + "x": 1284, + "y": 336.1333333333333 }, { - "x": 1062, - "y": 362 + "x": 1284, + "y": 118 }, { - "x": 1474, - "y": 362 + "x": 2026, + "y": 118 } ], "animated": false, @@ -1705,12 +1464,12 @@ "labelPercentage": 0, "route": [ { - "x": 1022, - "y": 1054.8333333333333 + "x": 1244, + "y": 396.7333333333333 }, { - "x": 1152, - "y": 1054.8333333333333 + "x": 1374, + "y": 396.7333333333333 } ], "animated": false, @@ -1745,20 +1504,20 @@ "labelPercentage": 0, "route": [ { - "x": 1022, - "y": 1188.8333333333333 + "x": 1244, + "y": 457.3333333333333 }, { - "x": 1112, - "y": 1188.8333333333333 + "x": 1334, + "y": 457.3333333333333 }, { - "x": 1112, - "y": 1447.3333333333333 + "x": 1334, + "y": 553.3333333333333 }, { - "x": 1152, - "y": 1447.3333333333333 + "x": 1374, + "y": 553.3333333333333 } ], "animated": false, @@ -1793,20 +1552,20 @@ "labelPercentage": 0, "route": [ { - "x": 1022, - "y": 1322.8333333333333 + "x": 1244, + "y": 517.9333333333333 }, { - "x": 1062, - "y": 1322.8333333333333 + "x": 1284, + "y": 517.9333333333333 }, { - "x": 1062, - "y": 1486.6666666666667 + "x": 1284, + "y": 592.6666666666666 }, { - "x": 1152, - "y": 1486.6666666666667 + "x": 1374, + "y": 592.6666666666666 } ], "animated": false, diff --git a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg index d0f70137b..a12a64bbf 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg @@ -1,24 +1,24 @@ -Just-in-time Access viaInfrastructureIndentity Provider2EngineersMachines1HTTPS://> kubectl> tsh> apiDB Clients22

Teleport

-

Identity Native Proxy

-
Audit LogCert Authority1SlackMattermostJiraPagerdutyEmail2sshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

+

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file From f8617d1560af55c8de2ebe30b6abcf34e498083b Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 11:36:01 -0700 Subject: [PATCH 04/31] refactor --- d2layouts/d2grid/grid.go | 65 +++++++++++++++++ d2layouts/d2grid/layout.go | 145 +++++++++++-------------------------- 2 files changed, 109 insertions(+), 101 deletions(-) create mode 100644 d2layouts/d2grid/grid.go diff --git a/d2layouts/d2grid/grid.go b/d2layouts/d2grid/grid.go new file mode 100644 index 000000000..29853fc8a --- /dev/null +++ b/d2layouts/d2grid/grid.go @@ -0,0 +1,65 @@ +package d2grid + +import ( + "strconv" + + "oss.terrastruct.com/d2/d2graph" +) + +type grid struct { + root *d2graph.Object + nodes []*d2graph.Object + rows int + columns int + + width float64 + height float64 +} + +func newGrid(root *d2graph.Object) *grid { + g := grid{root: root, nodes: root.ChildrenArray} + if root.Attributes.Rows != nil { + g.rows, _ = strconv.Atoi(root.Attributes.Rows.Value) + } + if root.Attributes.Columns != nil { + g.columns, _ = strconv.Atoi(root.Attributes.Columns.Value) + } + + // compute exact row/column count based on values entered + // TODO consider making this based on node dimensions + if g.rows == 0 { + // set rows based on number of columns + if g.columns == 0 { + // 0,0: put everything in one row + g.rows = 1 + g.columns = len(g.nodes) + } else { + g.rows = len(g.nodes) / g.columns + if len(g.nodes)%g.columns != 0 { + g.rows++ + } + } + } else if g.columns == 0 { + // set columns based on number of rows + g.columns = len(g.nodes) / g.rows + if len(g.nodes)%g.rows != 0 { + g.columns++ + } + } else { + // rows and columns specified (add more rows if needed) + capacity := g.rows * g.columns + for capacity < len(g.nodes) { + g.rows++ + capacity += g.columns + } + } + + return &g +} + +func (g *grid) shift(dx, dy float64) { + for _, obj := range g.nodes { + obj.TopLeft.X += dx + obj.TopLeft.Y += dy + } +} diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 05f4176f2..45966e3a2 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -4,7 +4,6 @@ import ( "context" "math" "sort" - "strconv" "oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/lib/geo" @@ -12,67 +11,11 @@ import ( "oss.terrastruct.com/util-go/go2" ) -const CONTAINER_PADDING = 60. -const HORIZONTAL_PAD = 40. -const VERTICAL_PAD = 40. - -type grid struct { - root *d2graph.Object - nodes []*d2graph.Object - rows int - columns int - - width float64 - height float64 -} - -func newGrid(root *d2graph.Object) *grid { - g := grid{root: root, nodes: root.ChildrenArray} - if root.Attributes.Rows != nil { - g.rows, _ = strconv.Atoi(root.Attributes.Rows.Value) - } - if root.Attributes.Columns != nil { - g.columns, _ = strconv.Atoi(root.Attributes.Columns.Value) - } - - // compute exact row/column count based on values entered - // TODO consider making this based on node dimensions - if g.rows == 0 { - // set rows based on number of columns - if g.columns == 0 { - // 0,0: put everything in one row - g.rows = 1 - g.columns = len(g.nodes) - } else { - g.rows = len(g.nodes) / g.columns - if len(g.nodes)%g.columns != 0 { - g.rows++ - } - } - } else if g.columns == 0 { - // set columns based on number of rows - g.columns = len(g.nodes) / g.rows - if len(g.nodes)%g.rows != 0 { - g.columns++ - } - } else { - // rows and columns specified (add more rows if needed) - capacity := g.rows * g.columns - for capacity < len(g.nodes) { - g.rows++ - capacity += g.columns - } - } - - return &g -} - -func (g *grid) shift(dx, dy float64) { - for _, obj := range g.nodes { - obj.TopLeft.X += dx - obj.TopLeft.Y += dy - } -} +const ( + CONTAINER_PADDING = 60 + HORIZONTAL_PAD = 40. + VERTICAL_PAD = 40. +) // Layout runs the grid layout on containers with rows/columns // Note: children are not allowed edges or descendants @@ -102,40 +45,6 @@ func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d } } -func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { - grid := newGrid(obj) - - // position nodes - cursor := geo.NewPoint(0, 0) - maxWidth := 0. - for i := 0; i < grid.rows; i++ { - maxHeight := 0. - for j := 0; j < grid.columns; j++ { - n := grid.nodes[i*grid.columns+j] - n.TopLeft = cursor.Copy() - cursor.X += n.Width + HORIZONTAL_PAD - maxHeight = math.Max(maxHeight, n.Height) - } - maxWidth = math.Max(maxWidth, cursor.X-HORIZONTAL_PAD) - cursor.X = 0 - cursor.Y += float64(maxHeight) + VERTICAL_PAD - } - grid.width = maxWidth - grid.height = cursor.Y - VERTICAL_PAD - - // position labels and icons - for _, n := range grid.nodes { - if n.Attributes.Icon != nil { - n.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) - n.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) - } else { - n.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) - } - } - - return grid, nil -} - func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*grid, objectOrder map[string]int, err error) { toRemove := make(map[*d2graph.Object]struct{}) grids := make(map[string]*grid) @@ -183,6 +92,40 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g return grids, objectOrder, nil } +func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { + grid := newGrid(obj) + + // position nodes + cursor := geo.NewPoint(0, 0) + maxWidth := 0. + for i := 0; i < grid.rows; i++ { + maxHeight := 0. + for j := 0; j < grid.columns; j++ { + n := grid.nodes[i*grid.columns+j] + n.TopLeft = cursor.Copy() + cursor.X += n.Width + HORIZONTAL_PAD + maxHeight = math.Max(maxHeight, n.Height) + } + maxWidth = math.Max(maxWidth, cursor.X-HORIZONTAL_PAD) + cursor.X = 0 + cursor.Y += float64(maxHeight) + VERTICAL_PAD + } + grid.width = maxWidth + grid.height = cursor.Y - VERTICAL_PAD + + // position labels and icons + for _, n := range grid.nodes { + if n.Attributes.Icon != nil { + n.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) + n.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } else { + n.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } + } + + return grid, nil +} + // cleanup restores the graph after the core layout engine finishes // - translating the grid to its position placed by the core layout engine // - restore the children of the grid @@ -195,26 +138,26 @@ func cleanup(g *d2graph.Graph, grids map[string]*grid, objectsOrder map[string]i objects = g.Objects } for _, obj := range objects { - if _, exists := grids[obj.AbsID()]; !exists { + grid, exists := grids[obj.AbsID()] + if !exists { continue } obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) - sd := grids[obj.AbsID()] // shift the grid from (0, 0) - sd.shift( + grid.shift( obj.TopLeft.X+CONTAINER_PADDING, obj.TopLeft.Y+CONTAINER_PADDING, ) obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = make([]*d2graph.Object, 0) - for _, child := range sd.nodes { + for _, child := range grid.nodes { obj.Children[child.ID] = child obj.ChildrenArray = append(obj.ChildrenArray, child) } - g.Objects = append(g.Objects, grids[obj.AbsID()].nodes...) + g.Objects = append(g.Objects, grid.nodes...) } sort.SliceStable(g.Objects, func(i, j int) bool { From abe27cdc26a39eee1b45d6e831653a2eb9c15ace Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 11:45:45 -0700 Subject: [PATCH 05/31] cleanup --- d2layouts/d2sequence/layout.go | 70 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go index cfae446c4..a2c7df0a5 100644 --- a/d2layouts/d2sequence/layout.go +++ b/d2layouts/d2sequence/layout.go @@ -13,6 +13,33 @@ import ( "oss.terrastruct.com/d2/lib/label" ) +// Layout runs the sequence diagram layout engine on objects of shape sequence_diagram +// +// 1. Traverse graph from root, skip objects with shape not `sequence_diagram` +// 2. Construct a sequence diagram from all descendant objects and edges +// 3. Remove those objects and edges from the main graph +// 4. Run layout on sequence diagrams +// 5. Set the resulting dimensions to the main graph shape +// 6. Run core layouts (still without sequence diagram innards) +// 7. Put back sequence diagram innards in correct location +func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) error { + sequenceDiagrams, objectOrder, edgeOrder, err := WithoutSequenceDiagrams(ctx, g) + if err != nil { + return err + } + + if g.Root.IsSequenceDiagram() { + // the sequence diagram is the only layout engine if the whole diagram is + // shape: sequence_diagram + g.Root.TopLeft = geo.NewPoint(0, 0) + } else if err := layout(ctx, g); err != nil { + return err + } + + cleanup(g, sequenceDiagrams, objectOrder, edgeOrder) + return nil +} + func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]*sequenceDiagram, map[string]int, map[string]int, error) { objectsToRemove := make(map[*d2graph.Object]struct{}) edgesToRemove := make(map[*d2graph.Edge]struct{}) @@ -69,33 +96,6 @@ func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string] return sequenceDiagrams, objectOrder, edgeOrder, nil } -// Layout runs the sequence diagram layout engine on objects of shape sequence_diagram -// -// 1. Traverse graph from root, skip objects with shape not `sequence_diagram` -// 2. Construct a sequence diagram from all descendant objects and edges -// 3. Remove those objects and edges from the main graph -// 4. Run layout on sequence diagrams -// 5. Set the resulting dimensions to the main graph shape -// 6. Run core layouts (still without sequence diagram innards) -// 7. Put back sequence diagram innards in correct location -func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) error { - sequenceDiagrams, objectOrder, edgeOrder, err := WithoutSequenceDiagrams(ctx, g) - if err != nil { - return err - } - - if g.Root.IsSequenceDiagram() { - // the sequence diagram is the only layout engine if the whole diagram is - // shape: sequence_diagram - g.Root.TopLeft = geo.NewPoint(0, 0) - } else if err := layout(ctx, g); err != nil { - return err - } - - cleanup(g, sequenceDiagrams, objectOrder, edgeOrder) - return nil -} - // layoutSequenceDiagram finds the edges inside the sequence diagram and performs the layout on the object descendants func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) (*sequenceDiagram, error) { var edges []*d2graph.Edge @@ -154,11 +154,11 @@ func cleanup(g *d2graph.Graph, sequenceDiagrams map[string]*sequenceDiagram, obj objects = g.Objects } for _, obj := range objects { - if _, exists := sequenceDiagrams[obj.AbsID()]; !exists { + sd, exists := sequenceDiagrams[obj.AbsID()] + if !exists { continue } obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) - sd := sequenceDiagrams[obj.AbsID()] // shift the sequence diagrams as they are always placed at (0, 0) with some padding sd.shift( @@ -181,12 +181,12 @@ func cleanup(g *d2graph.Graph, sequenceDiagrams map[string]*sequenceDiagram, obj } } - g.Edges = append(g.Edges, sequenceDiagrams[obj.AbsID()].messages...) - g.Edges = append(g.Edges, sequenceDiagrams[obj.AbsID()].lifelines...) - g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].actors...) - g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].notes...) - g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].groups...) - g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].spans...) + g.Edges = append(g.Edges, sd.messages...) + g.Edges = append(g.Edges, sd.lifelines...) + g.Objects = append(g.Objects, sd.actors...) + g.Objects = append(g.Objects, sd.notes...) + g.Objects = append(g.Objects, sd.groups...) + g.Objects = append(g.Objects, sd.spans...) } // no new objects, so just keep the same position From 06fb313d3e65a0b76f4ea927323a0e82fee8b7bf Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 11:52:12 -0700 Subject: [PATCH 06/31] values must be positive --- d2compiler/compile.go | 8 ++++---- d2compiler/compile_test.go | 2 +- d2layouts/d2grid/grid.go | 12 +++--------- .../d2compiler/TestCompile/grid_negative.exp.json | 2 +- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 4dd2badbb..66940ce56 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -368,8 +368,8 @@ func (c *compiler) compileReserved(attrs *d2graph.Attributes, f *d2ir.Field) { c.errorf(scalar, "non-integer rows %#v: %s", scalar.ScalarString(), err) return } - if v < 0 { - c.errorf(scalar, "rows must be a non-negative integer: %#v", scalar.ScalarString()) + if v <= 0 { + c.errorf(scalar, "rows must be a positive integer: %#v", scalar.ScalarString()) return } attrs.Rows = &d2graph.Scalar{} @@ -381,8 +381,8 @@ func (c *compiler) compileReserved(attrs *d2graph.Attributes, f *d2ir.Field) { c.errorf(scalar, "non-integer columns %#v: %s", scalar.ScalarString(), err) return } - if v < 0 { - c.errorf(scalar, "columns must be a non-negative integer: %#v", scalar.ScalarString()) + if v <= 0 { + c.errorf(scalar, "columns must be a positive integer: %#v", scalar.ScalarString()) return } attrs.Columns = &d2graph.Scalar{} diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 7dc218cae..2d6e63a95 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2286,7 +2286,7 @@ obj { columns: -200 } `, - expErr: `d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a non-negative integer: "-200"`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a positive integer: "-200"`, }, } diff --git a/d2layouts/d2grid/grid.go b/d2layouts/d2grid/grid.go index 29853fc8a..cd5e4ec8f 100644 --- a/d2layouts/d2grid/grid.go +++ b/d2layouts/d2grid/grid.go @@ -29,15 +29,9 @@ func newGrid(root *d2graph.Object) *grid { // TODO consider making this based on node dimensions if g.rows == 0 { // set rows based on number of columns - if g.columns == 0 { - // 0,0: put everything in one row - g.rows = 1 - g.columns = len(g.nodes) - } else { - g.rows = len(g.nodes) / g.columns - if len(g.nodes)%g.columns != 0 { - g.rows++ - } + g.rows = len(g.nodes) / g.columns + if len(g.nodes)%g.columns != 0 { + g.rows++ } } else if g.columns == 0 { // set columns based on number of rows diff --git a/testdata/d2compiler/TestCompile/grid_negative.exp.json b/testdata/d2compiler/TestCompile/grid_negative.exp.json index ff17efc56..5551871da 100644 --- a/testdata/d2compiler/TestCompile/grid_negative.exp.json +++ b/testdata/d2compiler/TestCompile/grid_negative.exp.json @@ -5,7 +5,7 @@ "errs": [ { "range": "d2/testdata/d2compiler/TestCompile/grid_negative.d2,2:10:28-2:14:32", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a non-negative integer: \"-200\"" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a positive integer: \"-200\"" } ] } From acd0638325fa77c8460c41c46c429092a4454808 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 12:59:54 -0700 Subject: [PATCH 07/31] evenly size grid nodes --- d2layouts/d2grid/grid.go | 45 +++++++++++++++++++++++++++++++++++--- d2layouts/d2grid/layout.go | 15 +++++-------- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/d2layouts/d2grid/grid.go b/d2layouts/d2grid/grid.go index cd5e4ec8f..4a743c60f 100644 --- a/d2layouts/d2grid/grid.go +++ b/d2layouts/d2grid/grid.go @@ -1,6 +1,7 @@ package d2grid import ( + "math" "strconv" "oss.terrastruct.com/d2/d2graph" @@ -12,8 +13,10 @@ type grid struct { rows int columns int - width float64 - height float64 + cellWidth float64 + cellHeight float64 + width float64 + height float64 } func newGrid(root *d2graph.Object) *grid { @@ -26,7 +29,6 @@ func newGrid(root *d2graph.Object) *grid { } // compute exact row/column count based on values entered - // TODO consider making this based on node dimensions if g.rows == 0 { // set rows based on number of columns g.rows = len(g.nodes) / g.columns @@ -48,6 +50,43 @@ func newGrid(root *d2graph.Object) *grid { } } + // if we have the following nodes for a 2 row, 3 column grid + // . ┌A──────────────────┐ ┌B─────┐ ┌C────────────┐ ┌D───────────┐ ┌E───────────────────┐ + // . │ │ │ │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ │ │ │ + // . └───────────────────┘ │ │ │ │ │ │ │ │ + // . │ │ └─────────────┘ │ │ │ │ + // . │ │ │ │ └────────────────────┘ + // . └──────┘ │ │ + // . └────────────┘ + // Then we must get the max width and max height to determine the grid cell size + // . maxWidth├────────────────────┤ + // . ┌A───────────────────┐ ┌B───────────────────┐ ┌C───────────────────┐ ┬maxHeight + // . │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ + // . └────────────────────┘ └────────────────────┘ └────────────────────┘ ┴ + // . ┌D───────────────────┐ ┌E───────────────────┐ + // . │ │ │ │ + // . │ │ │ │ + // . │ │ │ │ + // . │ │ │ │ + // . │ │ │ │ + // . │ │ │ │ + // . └────────────────────┘ └────────────────────┘ + var maxWidth, maxHeight float64 + for _, n := range g.nodes { + maxWidth = math.Max(maxWidth, n.Width) + maxHeight = math.Max(maxHeight, n.Height) + } + g.cellWidth = maxWidth + g.cellHeight = maxHeight + g.width = maxWidth + (float64(g.columns)-1)*(maxWidth+HORIZONTAL_PAD) + g.height = maxHeight + (float64(g.rows)-1)*(maxHeight+VERTICAL_PAD) + return &g } diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 45966e3a2..e9d68bccd 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -2,7 +2,6 @@ package d2grid import ( "context" - "math" "sort" "oss.terrastruct.com/d2/d2graph" @@ -69,7 +68,7 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g } obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = nil - obj.Box = geo.NewBox(nil, grid.width+CONTAINER_PADDING*2, grid.height+CONTAINER_PADDING*2) + obj.Box = geo.NewBox(nil, grid.width+2*CONTAINER_PADDING, grid.height+2*CONTAINER_PADDING) obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) grids[obj.AbsID()] = grid @@ -97,21 +96,17 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { // position nodes cursor := geo.NewPoint(0, 0) - maxWidth := 0. for i := 0; i < grid.rows; i++ { - maxHeight := 0. for j := 0; j < grid.columns; j++ { n := grid.nodes[i*grid.columns+j] + n.Width = grid.cellWidth + n.Height = grid.cellHeight n.TopLeft = cursor.Copy() - cursor.X += n.Width + HORIZONTAL_PAD - maxHeight = math.Max(maxHeight, n.Height) + cursor.X += grid.cellWidth + HORIZONTAL_PAD } - maxWidth = math.Max(maxWidth, cursor.X-HORIZONTAL_PAD) cursor.X = 0 - cursor.Y += float64(maxHeight) + VERTICAL_PAD + cursor.Y += float64(grid.cellHeight) + VERTICAL_PAD } - grid.width = maxWidth - grid.height = cursor.Y - VERTICAL_PAD // position labels and icons for _, n := range grid.nodes { From 13a8ca0e9fb9d459b27e4f738b46aebfcbf830b7 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 13:01:08 -0700 Subject: [PATCH 08/31] update test --- .../stable/teleport_grid/dagre/board.exp.json | 160 +++++++-------- .../stable/teleport_grid/dagre/sketch.exp.svg | 184 +++++++++--------- .../stable/teleport_grid/elk/board.exp.json | 168 ++++++++-------- .../stable/teleport_grid/elk/sketch.exp.svg | 184 +++++++++--------- 4 files changed, 348 insertions(+), 348 deletions(-) diff --git a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json index 3877af04c..d1ba12de3 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json @@ -8,10 +8,10 @@ "type": "rectangle", "pos": { "x": 0, - "y": 204 + "y": 203 }, "width": 272, - "height": 461, + "height": 464, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -90,10 +90,10 @@ "type": "rectangle", "pos": { "x": 1050, - "y": 283 + "y": 263 }, - "width": 584, - "height": 303, + "width": 764, + "height": 344, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -130,10 +130,10 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 2136, + "x": 2316, "y": 0 }, - "width": 820, + "width": 920, "height": 212, "opacity": 1, "strokeDash": 0, @@ -171,10 +171,10 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 2255, + "x": 2448, "y": 232 }, - "width": 582, + "width": 656, "height": 344, "opacity": 1, "strokeDash": 0, @@ -212,7 +212,7 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 2446, + "x": 2676, "y": 596 }, "width": 201, @@ -266,7 +266,7 @@ "type": "oval", "pos": { "x": 60, - "y": 264 + "y": 263 }, "width": 152, "height": 152, @@ -319,10 +319,10 @@ "type": "oval", "pos": { "x": 60, - "y": 456 + "y": 455 }, - "width": 149, - "height": 149, + "width": 152, + "height": 152, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -374,7 +374,7 @@ "x": 603, "y": 190 }, - "width": 107, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -415,7 +415,7 @@ "x": 603, "y": 296 }, - "width": 111, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -456,7 +456,7 @@ "x": 603, "y": 402 }, - "width": 79, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -497,7 +497,7 @@ "x": 603, "y": 508 }, - "width": 79, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -577,10 +577,10 @@ "type": "text", "pos": { "x": 1110, - "y": 343 + "y": 323 }, - "width": 122, - "height": 51, + "width": 302, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -617,11 +617,11 @@ "id": "teleport.inp", "type": "text", "pos": { - "x": 1272, - "y": 343 + "x": 1452, + "y": 323 }, "width": 302, - "height": 51, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -659,9 +659,9 @@ "type": "rectangle", "pos": { "x": 1110, - "y": 434 + "y": 455 }, - "width": 140, + "width": 302, "height": 92, "opacity": 1, "strokeDash": 0, @@ -711,10 +711,10 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 1290, - "y": 434 + "x": 1452, + "y": 455 }, - "width": 173, + "width": 302, "height": 92, "opacity": 1, "strokeDash": 0, @@ -764,10 +764,10 @@ "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 2196, + "x": 2376, "y": 60 }, - "width": 110, + "width": 128, "height": 92, "opacity": 1, "strokeDash": 0, @@ -817,11 +817,11 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 2346, + "x": 2544, "y": 60 }, "width": 128, - "height": 66, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -858,11 +858,11 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 2514, + "x": 2712, "y": 60 }, - "width": 72, - "height": 66, + "width": 128, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -899,11 +899,11 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 2626, + "x": 2880, "y": 60 }, - "width": 119, - "height": 66, + "width": 128, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -940,10 +940,10 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 2785, + "x": 3048, "y": 60 }, - "width": 111, + "width": 128, "height": 92, "opacity": 1, "strokeDash": 0, @@ -993,10 +993,10 @@ "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 2315, + "x": 2508, "y": 292 }, - "width": 95, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1046,7 +1046,7 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 2450, + "x": 2700, "y": 292 }, "width": 152, @@ -1099,10 +1099,10 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 2642, + "x": 2892, "y": 292 }, - "width": 122, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1152,10 +1152,10 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 2315, + "x": 2508, "y": 424 }, - "width": 138, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1205,10 +1205,10 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 2493, + "x": 2700, "y": 424 }, - "width": 108, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1258,10 +1258,10 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 2641, + "x": 2892, "y": 424 }, - "width": 136, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1434,19 +1434,19 @@ "labelPercentage": 0, "route": [ { - "x": 1592.4246575342465, - "y": 283 + "x": 1763.433789954338, + "y": 262.5 }, { - "x": 1826.4849315068493, - "y": 141.4 + "x": 2004.6867579908676, + "y": 137.3 }, { - "x": 1935.2, + "x": 2115.2, "y": 106 }, { - "x": 2136, + "x": 2316, "y": 106 } ], @@ -1483,19 +1483,19 @@ "labelPercentage": 0, "route": [ { - "x": 1634, - "y": 418.0985267034991 + "x": 1814, + "y": 416.09399684044234 }, { - "x": 1834.8, - "y": 406.81970534069984 + "x": 2014.8, + "y": 406.41879936808846 }, { - "x": 1959, + "x": 2141.6, "y": 404 }, { - "x": 2255, + "x": 2448, "y": 404 } ], @@ -1532,20 +1532,20 @@ "labelPercentage": 0, "route": [ { - "x": 1634, - "y": 501.98802946593 + "x": 1814, + "y": 510.2361769352291 }, { - "x": 1834.8, - "y": 548.397605893186 + "x": 2014.8, + "y": 550.0472353870458 }, { - "x": 1997.1, - "y": 576.1111951588503 + "x": 2187.1, + "y": 576.3143459915611 }, { - "x": 2445.5, - "y": 640.5559757942511 + "x": 2675.5, + "y": 641.5717299578059 } ], "isCurve": true, @@ -1581,20 +1581,20 @@ "labelPercentage": 0, "route": [ { - "x": 1634, - "y": 569.47605893186 + "x": 1814, + "y": 585.9723538704582 }, { - "x": 1834.8, - "y": 662.295211786372 + "x": 2014.8, + "y": 665.5944707740916 }, { - "x": 1997.1, - "y": 680.3274583963691 + "x": 2187.1, + "y": 680.2622362869198 }, { - "x": 2445.5, - "y": 659.6372919818457 + "x": 2675.5, + "y": 659.3111814345991 } ], "isCurve": true, diff --git a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg index 6269083ef..f6a003864 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg @@ -1,23 +1,23 @@ -Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

-

Identity Native Proxy

-
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

+

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file diff --git a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json index 0fad16a9e..791027e81 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json @@ -8,10 +8,10 @@ "type": "rectangle", "pos": { "x": 12, - "y": 196 + "y": 190 }, "width": 272, - "height": 461, + "height": 464, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -49,7 +49,7 @@ "type": "rectangle", "pos": { "x": 354, - "y": 122 + "y": 117 }, "width": 236, "height": 610, @@ -90,10 +90,10 @@ "type": "rectangle", "pos": { "x": 660, - "y": 275 + "y": 250 }, - "width": 584, - "height": 303, + "width": 764, + "height": 344, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -130,10 +130,10 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 2026, + "x": 2280, "y": 12 }, - "width": 820, + "width": 920, "height": 212, "opacity": 1, "strokeDash": 0, @@ -171,10 +171,10 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 1374, + "x": 1554, "y": 150 }, - "width": 582, + "width": 656, "height": 344, "opacity": 1, "strokeDash": 0, @@ -212,7 +212,7 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 1374, + "x": 1554, "y": 514 }, "width": 201, @@ -266,7 +266,7 @@ "type": "oval", "pos": { "x": 72, - "y": 256 + "y": 250 }, "width": 152, "height": 152, @@ -319,10 +319,10 @@ "type": "oval", "pos": { "x": 72, - "y": 448 + "y": 442 }, - "width": 149, - "height": 149, + "width": 152, + "height": 152, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -372,9 +372,9 @@ "type": "rectangle", "pos": { "x": 414, - "y": 182 + "y": 177 }, - "width": 107, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -413,9 +413,9 @@ "type": "rectangle", "pos": { "x": 414, - "y": 288 + "y": 283 }, - "width": 111, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -454,9 +454,9 @@ "type": "rectangle", "pos": { "x": 414, - "y": 394 + "y": 389 }, - "width": 79, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -495,9 +495,9 @@ "type": "rectangle", "pos": { "x": 414, - "y": 500 + "y": 495 }, - "width": 79, + "width": 116, "height": 66, "opacity": 1, "strokeDash": 0, @@ -536,7 +536,7 @@ "type": "rectangle", "pos": { "x": 414, - "y": 606 + "y": 601 }, "width": 116, "height": 66, @@ -577,10 +577,10 @@ "type": "text", "pos": { "x": 720, - "y": 335 + "y": 310 }, - "width": 122, - "height": 51, + "width": 302, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -617,11 +617,11 @@ "id": "teleport.inp", "type": "text", "pos": { - "x": 882, - "y": 335 + "x": 1062, + "y": 310 }, "width": 302, - "height": 51, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -659,9 +659,9 @@ "type": "rectangle", "pos": { "x": 720, - "y": 426 + "y": 442 }, - "width": 140, + "width": 302, "height": 92, "opacity": 1, "strokeDash": 0, @@ -711,10 +711,10 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 900, - "y": 426 + "x": 1062, + "y": 442 }, - "width": 173, + "width": 302, "height": 92, "opacity": 1, "strokeDash": 0, @@ -764,10 +764,10 @@ "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 2086, + "x": 2340, "y": 72 }, - "width": 110, + "width": 128, "height": 92, "opacity": 1, "strokeDash": 0, @@ -817,11 +817,11 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 2236, + "x": 2508, "y": 72 }, "width": 128, - "height": 66, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -858,11 +858,11 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 2404, + "x": 2676, "y": 72 }, - "width": 72, - "height": 66, + "width": 128, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -899,11 +899,11 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 2516, + "x": 2844, "y": 72 }, - "width": 119, - "height": 66, + "width": 128, + "height": 92, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -940,10 +940,10 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 2675, + "x": 3012, "y": 72 }, - "width": 111, + "width": 128, "height": 92, "opacity": 1, "strokeDash": 0, @@ -993,10 +993,10 @@ "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 1434, + "x": 1614, "y": 210 }, - "width": 95, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1046,7 +1046,7 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 1569, + "x": 1806, "y": 210 }, "width": 152, @@ -1099,10 +1099,10 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 1761, + "x": 1998, "y": 210 }, - "width": 122, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1152,10 +1152,10 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 1434, + "x": 1614, "y": 342 }, - "width": 138, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1205,10 +1205,10 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 1612, + "x": 1806, "y": 342 }, - "width": 108, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1258,10 +1258,10 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 1760, + "x": 1998, "y": 342 }, - "width": 136, + "width": 152, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1337,11 +1337,11 @@ "route": [ { "x": 284, - "y": 427.0333333333333 + "y": 422.93333333333334 }, { "x": 354, - "y": 427.0333333333333 + "y": 422.93333333333334 } ], "animated": false, @@ -1377,11 +1377,11 @@ "route": [ { "x": 590, - "y": 427.0333333333333 + "y": 422.93333333333334 }, { "x": 660, - "y": 427.0333333333333 + "y": 422.93333333333334 } ], "animated": false, @@ -1416,19 +1416,19 @@ "labelPercentage": 0, "route": [ { - "x": 1244, - "y": 336.1333333333333 + "x": 1424, + "y": 319.73333333333335 }, { - "x": 1284, - "y": 336.1333333333333 + "x": 1464, + "y": 319.73333333333335 }, { - "x": 1284, + "x": 1464, "y": 118 }, { - "x": 2026, + "x": 2280, "y": 118 } ], @@ -1464,12 +1464,12 @@ "labelPercentage": 0, "route": [ { - "x": 1244, - "y": 396.7333333333333 + "x": 1424, + "y": 388.53333333333336 }, { - "x": 1374, - "y": 396.7333333333333 + "x": 1554, + "y": 388.53333333333336 } ], "animated": false, @@ -1504,19 +1504,19 @@ "labelPercentage": 0, "route": [ { - "x": 1244, + "x": 1424, "y": 457.3333333333333 }, { - "x": 1334, + "x": 1514, "y": 457.3333333333333 }, { - "x": 1334, + "x": 1514, "y": 553.3333333333333 }, { - "x": 1374, + "x": 1554, "y": 553.3333333333333 } ], @@ -1552,20 +1552,20 @@ "labelPercentage": 0, "route": [ { - "x": 1244, - "y": 517.9333333333333 + "x": 1424, + "y": 526.1333333333333 }, { - "x": 1284, - "y": 517.9333333333333 + "x": 1464, + "y": 526.1333333333333 }, { - "x": 1284, - "y": 592.6666666666666 + "x": 1464, + "y": 592.6666666666667 }, { - "x": 1374, - "y": 592.6666666666666 + "x": 1554, + "y": 592.6666666666667 } ], "animated": false, diff --git a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg index a12a64bbf..1d5730d9b 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg @@ -1,23 +1,23 @@ -Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

-

Identity Native Proxy

-
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

+

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file From 0ed4bfe244746314eb040180c71bf2b641df0021 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 18:58:07 -0700 Subject: [PATCH 09/31] add dagger_grid test --- e2etests/stable_test.go | 1 + e2etests/testdata/files/dagger_grid.d2 | 25 ++ .../stable/dagger_grid/dagre/board.exp.json | 417 ++++++++++++++++++ .../stable/dagger_grid/dagre/sketch.exp.svg | 102 +++++ .../stable/dagger_grid/elk/board.exp.json | 417 ++++++++++++++++++ .../stable/dagger_grid/elk/sketch.exp.svg | 102 +++++ 6 files changed, 1064 insertions(+) create mode 100644 e2etests/testdata/files/dagger_grid.d2 create mode 100644 e2etests/testdata/stable/dagger_grid/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/dagger_grid/elk/board.exp.json create mode 100644 e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index 1fae58d41..4499dafca 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -2466,6 +2466,7 @@ scenarios: { }, loadFromFile(t, "arrowhead_scaling"), loadFromFile(t, "teleport_grid"), + loadFromFile(t, "dagger_grid"), } runa(t, tcs) diff --git a/e2etests/testdata/files/dagger_grid.d2 b/e2etests/testdata/files/dagger_grid.d2 new file mode 100644 index 000000000..66ea0432f --- /dev/null +++ b/e2etests/testdata/files/dagger_grid.d2 @@ -0,0 +1,25 @@ +todo root level grid: { + rows: 4 + + flow: { + width: 800 + height: 200 + } + + dagger engine: { + width: 800 + } + + any docker compatible runtime: { + width: 800 + } + + any ci: { + width: 800 + } + + windows + linux + macos + kubernetes +} diff --git a/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json new file mode 100644 index 000000000..bd49385e0 --- /dev/null +++ b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json @@ -0,0 +1,417 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "todo root level grid", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 1760, + "height": 1040, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "todo root level grid", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 222, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "todo root level grid.flow", + "type": "rectangle", + "pos": { + "x": 60, + "y": 60 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "flow", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 32, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.dagger engine", + "type": "rectangle", + "pos": { + "x": 900, + "y": 60 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "dagger engine", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 101, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.any docker compatible runtime", + "type": "rectangle", + "pos": { + "x": 60, + "y": 300 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "any docker compatible runtime", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 222, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.any ci", + "type": "rectangle", + "pos": { + "x": 900, + "y": 300 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "any ci", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 41, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.windows", + "type": "rectangle", + "pos": { + "x": 60, + "y": 540 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "windows", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.linux", + "type": "rectangle", + "pos": { + "x": 900, + "y": 540 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "linux", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 35, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.macos", + "type": "rectangle", + "pos": { + "x": 60, + "y": 780 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "macos", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 45, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.kubernetes", + "type": "rectangle", + "pos": { + "x": 900, + "y": 780 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "kubernetes", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 80, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg new file mode 100644 index 000000000..298a9765e --- /dev/null +++ b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg @@ -0,0 +1,102 @@ +todo root level gridflowdagger engineany docker compatible runtimeany ciwindowslinuxmacoskubernetes + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/dagger_grid/elk/board.exp.json b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json new file mode 100644 index 000000000..36716f307 --- /dev/null +++ b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json @@ -0,0 +1,417 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "todo root level grid", + "type": "rectangle", + "pos": { + "x": 12, + "y": 12 + }, + "width": 1760, + "height": 1040, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "todo root level grid", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 222, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "todo root level grid.flow", + "type": "rectangle", + "pos": { + "x": 72, + "y": 72 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "flow", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 32, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.dagger engine", + "type": "rectangle", + "pos": { + "x": 912, + "y": 72 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "dagger engine", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 101, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.any docker compatible runtime", + "type": "rectangle", + "pos": { + "x": 72, + "y": 312 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "any docker compatible runtime", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 222, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.any ci", + "type": "rectangle", + "pos": { + "x": 912, + "y": 312 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "any ci", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 41, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.windows", + "type": "rectangle", + "pos": { + "x": 72, + "y": 552 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "windows", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.linux", + "type": "rectangle", + "pos": { + "x": 912, + "y": 552 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "linux", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 35, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.macos", + "type": "rectangle", + "pos": { + "x": 72, + "y": 792 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "macos", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 45, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "todo root level grid.kubernetes", + "type": "rectangle", + "pos": { + "x": 912, + "y": 792 + }, + "width": 800, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "kubernetes", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 80, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg new file mode 100644 index 000000000..8ae60a5db --- /dev/null +++ b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg @@ -0,0 +1,102 @@ +todo root level gridflowdagger engineany docker compatible runtimeany ciwindowslinuxmacoskubernetes + + + \ No newline at end of file From c958269b03f2b9731a788e4b112482836ff89768 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 21:38:08 -0700 Subject: [PATCH 10/31] more dynamic grid sizing according to node sizes --- d2graph/grid.go | 2 +- d2layouts/d2grid/grid.go | 91 ++++---- d2layouts/d2grid/layout.go | 251 ++++++++++++++++++++--- e2etests/testdata/files/dagger_grid.d2 | 80 ++++++-- e2etests/testdata/files/teleport_grid.d2 | 2 +- 5 files changed, 315 insertions(+), 111 deletions(-) diff --git a/d2graph/grid.go b/d2graph/grid.go index b746f11a3..1ff029bba 100644 --- a/d2graph/grid.go +++ b/d2graph/grid.go @@ -1,6 +1,6 @@ package d2graph func (obj *Object) IsGrid() bool { - return obj != nil && obj.Attributes != nil && len(obj.ChildrenArray) != 0 && + return obj != nil && obj.Attributes != nil && (obj.Attributes.Rows != nil || obj.Attributes.Columns != nil) } diff --git a/d2layouts/d2grid/grid.go b/d2layouts/d2grid/grid.go index 4a743c60f..22cc23afd 100644 --- a/d2layouts/d2grid/grid.go +++ b/d2layouts/d2grid/grid.go @@ -1,7 +1,6 @@ package d2grid import ( - "math" "strconv" "oss.terrastruct.com/d2/d2graph" @@ -13,6 +12,8 @@ type grid struct { rows int columns int + rowDominant bool + cellWidth float64 cellHeight float64 width float64 @@ -29,64 +30,38 @@ func newGrid(root *d2graph.Object) *grid { } // compute exact row/column count based on values entered - if g.rows == 0 { - // set rows based on number of columns - g.rows = len(g.nodes) / g.columns - if len(g.nodes)%g.columns != 0 { - g.rows++ - } - } else if g.columns == 0 { - // set columns based on number of rows - g.columns = len(g.nodes) / g.rows - if len(g.nodes)%g.rows != 0 { - g.columns++ - } + if g.columns == 0 { + g.rowDominant = true + } else if g.rows == 0 { + g.rowDominant = false } else { - // rows and columns specified (add more rows if needed) + // if keyword rows is first, rows are primary, columns secondary. + if root.Attributes.Rows.MapKey.Range.Before(root.Attributes.Columns.MapKey.Range) { + g.rowDominant = true + } + + // rows and columns specified, but we want to continue naturally if user enters more nodes + // e.g. 2 rows, 3 columns specified + g node added: │ with 3 columns, 2 rows: + // . original add row add column │ original add row add column + // . ┌───────┐ ┌───────┐ ┌─────────┐ │ ┌───────┐ ┌───────┐ ┌─────────┐ + // . │ a b c │ │ a b c │ │ a b c d │ │ │ a c e │ │ a d g │ │ a c e g │ + // . │ d e f │ │ d e f │ │ e f g │ │ │ b d f │ │ b e │ │ b d f │ + // . └───────┘ │ g │ └─────────┘ │ └───────┘ │ c f │ └─────────┘ + // . └───────┘ ▲ │ └───────┘ ▲ + // . ▲ └─existing nodes modified │ ▲ └─existing nodes preserved + // . └─existing rows preserved │ └─existing rows modified capacity := g.rows * g.columns for capacity < len(g.nodes) { - g.rows++ - capacity += g.columns + if g.rowDominant { + g.rows++ + capacity += g.columns + } else { + g.columns++ + capacity += g.rows + } } } - // if we have the following nodes for a 2 row, 3 column grid - // . ┌A──────────────────┐ ┌B─────┐ ┌C────────────┐ ┌D───────────┐ ┌E───────────────────┐ - // . │ │ │ │ │ │ │ │ │ │ - // . │ │ │ │ │ │ │ │ │ │ - // . └───────────────────┘ │ │ │ │ │ │ │ │ - // . │ │ └─────────────┘ │ │ │ │ - // . │ │ │ │ └────────────────────┘ - // . └──────┘ │ │ - // . └────────────┘ - // Then we must get the max width and max height to determine the grid cell size - // . maxWidth├────────────────────┤ - // . ┌A───────────────────┐ ┌B───────────────────┐ ┌C───────────────────┐ ┬maxHeight - // . │ │ │ │ │ │ │ - // . │ │ │ │ │ │ │ - // . │ │ │ │ │ │ │ - // . │ │ │ │ │ │ │ - // . │ │ │ │ │ │ │ - // . │ │ │ │ │ │ │ - // . └────────────────────┘ └────────────────────┘ └────────────────────┘ ┴ - // . ┌D───────────────────┐ ┌E───────────────────┐ - // . │ │ │ │ - // . │ │ │ │ - // . │ │ │ │ - // . │ │ │ │ - // . │ │ │ │ - // . │ │ │ │ - // . └────────────────────┘ └────────────────────┘ - var maxWidth, maxHeight float64 - for _, n := range g.nodes { - maxWidth = math.Max(maxWidth, n.Width) - maxHeight = math.Max(maxHeight, n.Height) - } - g.cellWidth = maxWidth - g.cellHeight = maxHeight - g.width = maxWidth + (float64(g.columns)-1)*(maxWidth+HORIZONTAL_PAD) - g.height = maxHeight + (float64(g.rows)-1)*(maxHeight+VERTICAL_PAD) - return &g } @@ -96,3 +71,13 @@ func (g *grid) shift(dx, dy float64) { obj.TopLeft.Y += dy } } + +func (g *grid) cleanup(obj *d2graph.Object, graph *d2graph.Graph) { + obj.Children = make(map[string]*d2graph.Object) + obj.ChildrenArray = make([]*d2graph.Object, 0) + for _, child := range g.nodes { + obj.Children[child.ID] = child + obj.ChildrenArray = append(obj.ChildrenArray, child) + } + graph.Objects = append(graph.Objects, g.nodes...) +} diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index e9d68bccd..755146535 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -2,6 +2,7 @@ package d2grid import ( "context" + "math" "sort" "oss.terrastruct.com/d2/d2graph" @@ -33,7 +34,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d return err } - if g.Root.IsGrid() { + if g.Root.IsGrid() && len(g.Root.ChildrenArray) != 0 { g.Root.TopLeft = geo.NewPoint(0, 0) } else if err := layout(ctx, g); err != nil { return err @@ -93,20 +94,207 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { grid := newGrid(obj) + // assume we have the following nodes to layout: + // . ┌A──────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐ + // . └───────────────┘ │ │ │ │ │ │ │ │ + // . │ │ └──────────┘ │ │ │ │ + // . │ │ │ │ └─────────────────┘ + // . └───┘ │ │ + // . └─────────┘ + // Note: if the grid is row dominant, all nodes should be the same height (same width if column dominant) + // . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐ + // . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │ │ │ │ + // . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │ │ │ │ + // . │ │ │ │ │ │ │ │ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤ + // . │ │ ├ ─ ┤ │ │ │ │ │ │ + // . └──────────────┘ └───┘ └──────────┘ └─────────┘ └─────────────────┘ - // position nodes - cursor := geo.NewPoint(0, 0) - for i := 0; i < grid.rows; i++ { - for j := 0; j < grid.columns; j++ { - n := grid.nodes[i*grid.columns+j] - n.Width = grid.cellWidth - n.Height = grid.cellHeight - n.TopLeft = cursor.Copy() - cursor.X += grid.cellWidth + HORIZONTAL_PAD - } - cursor.X = 0 - cursor.Y += float64(grid.cellHeight) + VERTICAL_PAD + // we want to split up the total width across the N rows or columns as evenly as possible + var totalWidth, totalHeight float64 + for _, n := range grid.nodes { + totalWidth += n.Width + totalHeight += n.Height } + totalWidth += HORIZONTAL_PAD * float64(len(grid.nodes)-1) + totalHeight += VERTICAL_PAD * float64(len(grid.nodes)-1) + + layout := [][]int{{}} + if grid.rowDominant { + targetWidth := totalWidth / float64(grid.rows) + rowWidth := 0. + rowIndex := 0 + for i, n := range grid.nodes { + layout[rowIndex] = append(layout[rowIndex], i) + rowWidth += n.Width + HORIZONTAL_PAD + // add a new row if we pass the target width and there are more nodes + if rowWidth > targetWidth && i < len(grid.nodes)-1 { + layout = append(layout, []int{}) + rowIndex++ + rowWidth = 0 + } + } + } else { + targetHeight := totalHeight / float64(grid.columns) + columnHeight := 0. + columnIndex := 0 + for i, n := range grid.nodes { + layout[columnIndex] = append(layout[columnIndex], i) + columnHeight += n.Height + VERTICAL_PAD + if columnHeight > targetHeight && i < len(grid.nodes)-1 { + layout = append(layout, []int{}) + columnIndex++ + columnHeight = 0 + } + } + } + + cursor := geo.NewPoint(0, 0) + var maxY, maxX float64 + if grid.rowDominant { + // if we have 2 rows, then each row's nodes should have the same height + // . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C) + // . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │ + // . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │ + // . │ │ │ │ │ │ │ + // . └──────────────┘ └───┘ └──────────┘ ┴ + // . ┌D────────┐ ┌E────────────────┐ ┬ maxHeight(D,E) + // . │ │ │ │ │ + // . │ │ │ │ │ + // . │ │ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤ │ + // . │ │ │ │ │ + // . └─────────┘ └─────────────────┘ ┴ + rowWidths := []float64{} + for _, row := range layout { + rowHeight := 0. + for _, nodeIndex := range row { + n := grid.nodes[nodeIndex] + n.TopLeft = cursor.Copy() + cursor.X += n.Width + HORIZONTAL_PAD + rowHeight = math.Max(rowHeight, n.Height) + } + rowWidth := cursor.X - HORIZONTAL_PAD + rowWidths = append(rowWidths, rowWidth) + maxX = math.Max(maxX, rowWidth) + + // set all nodes in row to the same height + for _, nodeIndex := range row { + n := grid.nodes[nodeIndex] + n.Height = rowHeight + } + + // new row + cursor.X = 0 + cursor.Y += rowHeight + VERTICAL_PAD + } + maxY = cursor.Y - VERTICAL_PAD + + // then expand thinnest nodes to make each row the same width + // . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C) + // . │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ + // . │ │ │ │ │ │ │ + // . └──────────────┘ └───┘ └──────────┘ ┴ + // . ┌D────────┬────┐ ┌E────────────────┐ ┬ maxHeight(D,E) + // . │ │ │ │ │ + // . │ │ │ │ │ │ + // . │ │ │ │ │ + // . │ │ │ │ │ │ + // . └─────────┴────┘ └─────────────────┘ ┴ + for i, row := range layout { + rowWidth := rowWidths[i] + if rowWidth == maxX { + continue + } + delta := maxX - rowWidth + nodes := []*d2graph.Object{} + var widest float64 + for _, nodeIndex := range row { + n := grid.nodes[nodeIndex] + widest = math.Max(widest, n.Width) + nodes = append(nodes, n) + } + sort.Slice(nodes, func(i, j int) bool { + return nodes[i].Width < nodes[j].Width + }) + // expand smaller nodes to fill remaining space + for _, n := range nodes { + if n.Width < widest { + var index int + for i, nodeIndex := range row { + if n == grid.nodes[nodeIndex] { + index = i + break + } + } + grow := math.Min(widest-n.Width, delta) + n.Width += grow + // shift following nodes + for i := index + 1; i < len(row); i++ { + grid.nodes[row[i]].TopLeft.X += grow + } + delta -= grow + if delta <= 0 { + break + } + } + } + if delta > 0 { + grow := delta / float64(len(row)) + for i := len(row) - 1; i >= 0; i-- { + n := grid.nodes[row[i]] + n.TopLeft.X += grow * float64(i) + n.Width += grow + delta -= grow + } + } + } + } else { + // if we have 3 columns, then each column's nodes should have the same width + // . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤ + // . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐ + // . └──────────────┘ │ │ │ │ + // . ┌B──┬──────────┐ └──────────┘ │ │ + // . │ │ ┌D────────┬┐ └─────────────────┘ + // . │ │ │ │ │ + // . │ │ │ ││ + // . └───┴──────────┘ │ │ + // . │ ││ + // . └─────────┴┘ + for _, column := range layout { + columnWidth := 0. + for _, nodeIndex := range column { + n := grid.nodes[nodeIndex] + n.TopLeft = cursor.Copy() + cursor.Y += n.Height + VERTICAL_PAD + columnWidth = math.Max(columnWidth, n.Width) + } + maxY = math.Max(maxY, cursor.Y-VERTICAL_PAD) + // set all nodes in column to the same width + for _, nodeIndex := range column { + n := grid.nodes[nodeIndex] + n.Width = columnWidth + } + + // new column + cursor.Y = 0 + cursor.X += columnWidth + HORIZONTAL_PAD + } + maxX = cursor.X - HORIZONTAL_PAD + // then expand shortest nodes to make each column the same height + // . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤ + // . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐ + // . ├ ─ ─ ─ ─ ─ ─ ┤ │ │ │ │ + // . │ │ └──────────┘ │ │ + // . └──────────────┘ ┌D─────────┐ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤ + // . ┌B─────────────┐ │ │ │ │ + // . │ │ │ │ │ │ + // . │ │ │ │ │ │ + // . │ │ │ │ │ │ + // . └──────────────┘ └──────────┘ └─────────────────┘ + // TODO see rows + } + grid.width = maxX + grid.height = maxY // position labels and icons for _, n := range grid.nodes { @@ -125,37 +313,32 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { // - translating the grid to its position placed by the core layout engine // - restore the children of the grid // - sorts objects to their original graph order -func cleanup(g *d2graph.Graph, grids map[string]*grid, objectsOrder map[string]int) { - var objects []*d2graph.Object - if g.Root.IsGrid() { - objects = []*d2graph.Object{g.Root} - } else { - objects = g.Objects +func cleanup(graph *d2graph.Graph, grids map[string]*grid, objectsOrder map[string]int) { + defer func() { + sort.SliceStable(graph.Objects, func(i, j int) bool { + return objectsOrder[graph.Objects[i].AbsID()] < objectsOrder[graph.Objects[j].AbsID()] + }) + }() + + if graph.Root.IsGrid() { + grid, exists := grids[graph.Root.AbsID()] + if exists { + grid.cleanup(graph.Root, graph) + return + } } - for _, obj := range objects { + + for _, obj := range graph.Objects { grid, exists := grids[obj.AbsID()] if !exists { continue } obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) - // shift the grid from (0, 0) grid.shift( obj.TopLeft.X+CONTAINER_PADDING, obj.TopLeft.Y+CONTAINER_PADDING, ) - - obj.Children = make(map[string]*d2graph.Object) - obj.ChildrenArray = make([]*d2graph.Object, 0) - for _, child := range grid.nodes { - obj.Children[child.ID] = child - obj.ChildrenArray = append(obj.ChildrenArray, child) - } - - g.Objects = append(g.Objects, grid.nodes...) + grid.cleanup(obj, graph) } - - sort.SliceStable(g.Objects, func(i, j int) bool { - return objectsOrder[g.Objects[i].AbsID()] < objectsOrder[g.Objects[j].AbsID()] - }) } diff --git a/e2etests/testdata/files/dagger_grid.d2 b/e2etests/testdata/files/dagger_grid.d2 index 66ea0432f..b3db8ac9a 100644 --- a/e2etests/testdata/files/dagger_grid.d2 +++ b/e2etests/testdata/files/dagger_grid.d2 @@ -1,25 +1,61 @@ -todo root level grid: { - rows: 4 +rows: 4 +style.fill: black - flow: { - width: 800 - height: 200 +flow: "" { + width: 800 + height: 200 + style: { + fill: cornflowerblue } - - dagger engine: { - width: 800 - } - - any docker compatible runtime: { - width: 800 - } - - any ci: { - width: 800 - } - - windows - linux - macos - kubernetes +} + +DAGGER ENGINE: { + width: 800 + style: { + fill: beige + stroke: darkcyan + font-color: blue + stroke-width: 8 + } +} + +ANY DOCKER COMPATIBLE RUNTIME: { + width: 800 + style: { + fill: lightcyan + stroke: darkcyan + font-color: black + stroke-width: 8 + } + icon: https://icons.terrastruct.com/dev%2Fdocker.svg +} + +ANY CI: { + style: { + fill: gold + stroke: maroon + font-color: maroon + stroke-width: 8 + } +} + +WINDOWS.style: { + font-color: white + fill: darkcyan + stroke: black +} +LINUX.style: { + font-color: white + fill: darkcyan + stroke: black +} +MACOS.style: { + font-color: white + fill: darkcyan + stroke: black +} +KUBERNETES.style: { + font-color: white + fill: darkcyan + stroke: black } diff --git a/e2etests/testdata/files/teleport_grid.d2 b/e2etests/testdata/files/teleport_grid.d2 index fc8e6476e..ca6b0acac 100644 --- a/e2etests/testdata/files/teleport_grid.d2 +++ b/e2etests/testdata/files/teleport_grid.d2 @@ -9,7 +9,7 @@ teleport -> identity provider teleport <- identity provider users: "" { - rows: 2 + columns: 1 Engineers: { shape: circle From bb090becb88489fb9fa03811b57ec22ab533f3ee Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 3 Apr 2023 21:38:31 -0700 Subject: [PATCH 11/31] update tests --- .../stable/dagger_grid/dagre/board.exp.json | 349 ++++++++--------- .../stable/dagger_grid/dagre/sketch.exp.svg | 163 ++++---- .../stable/dagger_grid/elk/board.exp.json | 353 ++++++++---------- .../stable/dagger_grid/elk/sketch.exp.svg | 163 ++++---- .../stable/teleport_grid/dagre/board.exp.json | 144 +++---- .../stable/teleport_grid/dagre/sketch.exp.svg | 184 ++++----- .../stable/teleport_grid/elk/board.exp.json | 152 ++++---- .../stable/teleport_grid/elk/sketch.exp.svg | 184 ++++----- 8 files changed, 810 insertions(+), 882 deletions(-) diff --git a/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json index bd49385e0..b438f9716 100644 --- a/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json @@ -4,19 +4,19 @@ "fontFamily": "SourceSansPro", "shapes": [ { - "id": "todo root level grid", + "id": "flow", "type": "rectangle", "pos": { "x": 0, "y": 0 }, - "width": 1760, - "height": 1040, + "width": 800, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B4", + "fill": "cornflowerblue", "stroke": "B1", "shadow": false, "3d": false, @@ -30,35 +30,129 @@ "fields": null, "methods": null, "columns": null, - "label": "todo root level grid", - "fontSize": 28, + "label": "", + "fontSize": 16, "fontFamily": "DEFAULT", "language": "", "color": "N1", "italic": false, - "bold": false, + "bold": true, "underline": false, - "labelWidth": 222, - "labelHeight": 36, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "DAGGER ENGINE", + "type": "rectangle", + "pos": { + "x": 0, + "y": 240 + }, + "width": 800, + "height": 61, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 8, + "borderRadius": 0, + "fill": "beige", + "stroke": "darkcyan", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "DAGGER ENGINE", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "blue", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 114, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "ANY DOCKER COMPATIBLE RUNTIME", + "type": "rectangle", + "pos": { + "x": 0, + "y": 341 + }, + "width": 800, + "height": 87, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 8, + "borderRadius": 0, + "fill": "lightcyan", + "stroke": "darkcyan", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/docker.svg", + "RawPath": "/dev%2Fdocker.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ANY DOCKER COMPATIBLE RUNTIME", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "black", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 255, + "labelHeight": 21, "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, { - "id": "todo root level grid.flow", + "id": "ANY CI", "type": "rectangle", "pos": { - "x": 60, - "y": 60 + "x": 0, + "y": 468 }, - "width": 800, - "height": 200, + "width": 139, + "height": 66, "opacity": 1, "strokeDash": 0, - "strokeWidth": 2, + "strokeWidth": 8, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "gold", + "stroke": "maroon", "shadow": false, "3d": false, "multiple": false, @@ -71,35 +165,35 @@ "fields": null, "methods": null, "columns": null, - "label": "flow", + "label": "ANY CI", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "maroon", "italic": false, "bold": true, "underline": false, - "labelWidth": 32, + "labelWidth": 46, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.dagger engine", + "id": "WINDOWS", "type": "rectangle", "pos": { - "x": 900, - "y": 60 + "x": 179, + "y": 468 }, - "width": 800, - "height": 200, + "width": 117, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -112,35 +206,35 @@ "fields": null, "methods": null, "columns": null, - "label": "dagger engine", + "label": "WINDOWS", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 101, + "labelWidth": 72, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.any docker compatible runtime", + "id": "LINUX", "type": "rectangle", "pos": { - "x": 60, - "y": 300 + "x": 336, + "y": 468 }, - "width": 800, - "height": 200, + "width": 139, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -153,35 +247,35 @@ "fields": null, "methods": null, "columns": null, - "label": "any docker compatible runtime", + "label": "LINUX", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 222, + "labelWidth": 43, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.any ci", + "id": "MACOS", "type": "rectangle", "pos": { - "x": 900, - "y": 300 + "x": 515, + "y": 468 }, - "width": 800, - "height": 200, + "width": 106, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -194,35 +288,35 @@ "fields": null, "methods": null, "columns": null, - "label": "any ci", + "label": "MACOS", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 41, + "labelWidth": 50, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.windows", + "id": "KUBERNETES", "type": "rectangle", "pos": { - "x": 60, - "y": 540 + "x": 661, + "y": 468 }, - "width": 800, - "height": 200, + "width": 139, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -235,142 +329,19 @@ "fields": null, "methods": null, "columns": null, - "label": "windows", + "label": "KUBERNETES", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 64, + "labelWidth": 94, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 - }, - { - "id": "todo root level grid.linux", - "type": "rectangle", - "pos": { - "x": 900, - "y": 540 - }, - "width": 800, - "height": 200, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "linux", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 35, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "todo root level grid.macos", - "type": "rectangle", - "pos": { - "x": 60, - "y": 780 - }, - "width": 800, - "height": 200, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "macos", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 45, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "todo root level grid.kubernetes", - "type": "rectangle", - "pos": { - "x": 900, - "y": 780 - }, - "width": 800, - "height": 200, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "kubernetes", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 80, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 + "level": 1 } ], "connections": [], @@ -387,7 +358,7 @@ "strokeDash": 0, "strokeWidth": 0, "borderRadius": 0, - "fill": "N7", + "fill": "black", "stroke": "", "shadow": false, "3d": false, diff --git a/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg index 298a9765e..2e9ae781c 100644 --- a/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg @@ -1,17 +1,10 @@ -todo root level gridflowdagger engineany docker compatible runtimeany ciwindowslinuxmacoskubernetes - + .d2-1379472985 .fill-N1{fill:#0A0F25;} + .d2-1379472985 .fill-N2{fill:#676C7E;} + .d2-1379472985 .fill-N3{fill:#9499AB;} + .d2-1379472985 .fill-N4{fill:#CFD2DD;} + .d2-1379472985 .fill-N5{fill:#DEE1EB;} + .d2-1379472985 .fill-N6{fill:#EEF1F8;} + .d2-1379472985 .fill-N7{fill:#FFFFFF;} + .d2-1379472985 .fill-B1{fill:#0D32B2;} + .d2-1379472985 .fill-B2{fill:#0D32B2;} + .d2-1379472985 .fill-B3{fill:#E3E9FD;} + .d2-1379472985 .fill-B4{fill:#E3E9FD;} + .d2-1379472985 .fill-B5{fill:#EDF0FD;} + .d2-1379472985 .fill-B6{fill:#F7F8FE;} + .d2-1379472985 .fill-AA2{fill:#4A6FF3;} + .d2-1379472985 .fill-AA4{fill:#EDF0FD;} + .d2-1379472985 .fill-AA5{fill:#F7F8FE;} + .d2-1379472985 .fill-AB4{fill:#EDF0FD;} + .d2-1379472985 .fill-AB5{fill:#F7F8FE;} + .d2-1379472985 .stroke-N1{stroke:#0A0F25;} + .d2-1379472985 .stroke-N2{stroke:#676C7E;} + .d2-1379472985 .stroke-N3{stroke:#9499AB;} + .d2-1379472985 .stroke-N4{stroke:#CFD2DD;} + .d2-1379472985 .stroke-N5{stroke:#DEE1EB;} + .d2-1379472985 .stroke-N6{stroke:#EEF1F8;} + .d2-1379472985 .stroke-N7{stroke:#FFFFFF;} + .d2-1379472985 .stroke-B1{stroke:#0D32B2;} + .d2-1379472985 .stroke-B2{stroke:#0D32B2;} + .d2-1379472985 .stroke-B3{stroke:#E3E9FD;} + .d2-1379472985 .stroke-B4{stroke:#E3E9FD;} + .d2-1379472985 .stroke-B5{stroke:#EDF0FD;} + .d2-1379472985 .stroke-B6{stroke:#F7F8FE;} + .d2-1379472985 .stroke-AA2{stroke:#4A6FF3;} + .d2-1379472985 .stroke-AA4{stroke:#EDF0FD;} + .d2-1379472985 .stroke-AA5{stroke:#F7F8FE;} + .d2-1379472985 .stroke-AB4{stroke:#EDF0FD;} + .d2-1379472985 .stroke-AB5{stroke:#F7F8FE;} + .d2-1379472985 .background-color-N1{background-color:#0A0F25;} + .d2-1379472985 .background-color-N2{background-color:#676C7E;} + .d2-1379472985 .background-color-N3{background-color:#9499AB;} + .d2-1379472985 .background-color-N4{background-color:#CFD2DD;} + .d2-1379472985 .background-color-N5{background-color:#DEE1EB;} + .d2-1379472985 .background-color-N6{background-color:#EEF1F8;} + .d2-1379472985 .background-color-N7{background-color:#FFFFFF;} + .d2-1379472985 .background-color-B1{background-color:#0D32B2;} + .d2-1379472985 .background-color-B2{background-color:#0D32B2;} + .d2-1379472985 .background-color-B3{background-color:#E3E9FD;} + .d2-1379472985 .background-color-B4{background-color:#E3E9FD;} + .d2-1379472985 .background-color-B5{background-color:#EDF0FD;} + .d2-1379472985 .background-color-B6{background-color:#F7F8FE;} + .d2-1379472985 .background-color-AA2{background-color:#4A6FF3;} + .d2-1379472985 .background-color-AA4{background-color:#EDF0FD;} + .d2-1379472985 .background-color-AA5{background-color:#F7F8FE;} + .d2-1379472985 .background-color-AB4{background-color:#EDF0FD;} + .d2-1379472985 .background-color-AB5{background-color:#F7F8FE;} + .d2-1379472985 .color-N1{color:#0A0F25;} + .d2-1379472985 .color-N2{color:#676C7E;} + .d2-1379472985 .color-N3{color:#9499AB;} + .d2-1379472985 .color-N4{color:#CFD2DD;} + .d2-1379472985 .color-N5{color:#DEE1EB;} + .d2-1379472985 .color-N6{color:#EEF1F8;} + .d2-1379472985 .color-N7{color:#FFFFFF;} + .d2-1379472985 .color-B1{color:#0D32B2;} + .d2-1379472985 .color-B2{color:#0D32B2;} + .d2-1379472985 .color-B3{color:#E3E9FD;} + .d2-1379472985 .color-B4{color:#E3E9FD;} + .d2-1379472985 .color-B5{color:#EDF0FD;} + .d2-1379472985 .color-B6{color:#F7F8FE;} + .d2-1379472985 .color-AA2{color:#4A6FF3;} + .d2-1379472985 .color-AA4{color:#EDF0FD;} + .d2-1379472985 .color-AA5{color:#F7F8FE;} + .d2-1379472985 .color-AB4{color:#EDF0FD;} + .d2-1379472985 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES + \ No newline at end of file diff --git a/e2etests/testdata/stable/dagger_grid/elk/board.exp.json b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json index 36716f307..b438f9716 100644 --- a/e2etests/testdata/stable/dagger_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json @@ -4,19 +4,19 @@ "fontFamily": "SourceSansPro", "shapes": [ { - "id": "todo root level grid", + "id": "flow", "type": "rectangle", "pos": { - "x": 12, - "y": 12 + "x": 0, + "y": 0 }, - "width": 1760, - "height": 1040, + "width": 800, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B4", + "fill": "cornflowerblue", "stroke": "B1", "shadow": false, "3d": false, @@ -30,35 +30,129 @@ "fields": null, "methods": null, "columns": null, - "label": "todo root level grid", - "fontSize": 28, + "label": "", + "fontSize": 16, "fontFamily": "DEFAULT", "language": "", "color": "N1", "italic": false, - "bold": false, + "bold": true, "underline": false, - "labelWidth": 222, - "labelHeight": 36, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "DAGGER ENGINE", + "type": "rectangle", + "pos": { + "x": 0, + "y": 240 + }, + "width": 800, + "height": 61, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 8, + "borderRadius": 0, + "fill": "beige", + "stroke": "darkcyan", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "DAGGER ENGINE", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "blue", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 114, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "ANY DOCKER COMPATIBLE RUNTIME", + "type": "rectangle", + "pos": { + "x": 0, + "y": 341 + }, + "width": 800, + "height": 87, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 8, + "borderRadius": 0, + "fill": "lightcyan", + "stroke": "darkcyan", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/docker.svg", + "RawPath": "/dev%2Fdocker.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "iconPosition": "INSIDE_MIDDLE_CENTER", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ANY DOCKER COMPATIBLE RUNTIME", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "black", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 255, + "labelHeight": 21, "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, { - "id": "todo root level grid.flow", + "id": "ANY CI", "type": "rectangle", "pos": { - "x": 72, - "y": 72 + "x": 0, + "y": 468 }, - "width": 800, - "height": 200, + "width": 139, + "height": 66, "opacity": 1, "strokeDash": 0, - "strokeWidth": 2, + "strokeWidth": 8, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "gold", + "stroke": "maroon", "shadow": false, "3d": false, "multiple": false, @@ -71,35 +165,35 @@ "fields": null, "methods": null, "columns": null, - "label": "flow", + "label": "ANY CI", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "maroon", "italic": false, "bold": true, "underline": false, - "labelWidth": 32, + "labelWidth": 46, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.dagger engine", + "id": "WINDOWS", "type": "rectangle", "pos": { - "x": 912, - "y": 72 + "x": 179, + "y": 468 }, - "width": 800, - "height": 200, + "width": 117, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -112,35 +206,35 @@ "fields": null, "methods": null, "columns": null, - "label": "dagger engine", + "label": "WINDOWS", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 101, + "labelWidth": 72, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.any docker compatible runtime", + "id": "LINUX", "type": "rectangle", "pos": { - "x": 72, - "y": 312 + "x": 336, + "y": 468 }, - "width": 800, - "height": 200, + "width": 139, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -153,35 +247,35 @@ "fields": null, "methods": null, "columns": null, - "label": "any docker compatible runtime", + "label": "LINUX", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 222, + "labelWidth": 43, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.any ci", + "id": "MACOS", "type": "rectangle", "pos": { - "x": 912, - "y": 312 + "x": 515, + "y": 468 }, - "width": 800, - "height": 200, + "width": 106, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -194,35 +288,35 @@ "fields": null, "methods": null, "columns": null, - "label": "any ci", + "label": "MACOS", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 41, + "labelWidth": 50, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 + "level": 1 }, { - "id": "todo root level grid.windows", + "id": "KUBERNETES", "type": "rectangle", "pos": { - "x": 72, - "y": 552 + "x": 661, + "y": 468 }, - "width": 800, - "height": 200, + "width": 139, + "height": 66, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, "borderRadius": 0, - "fill": "B5", - "stroke": "B1", + "fill": "darkcyan", + "stroke": "black", "shadow": false, "3d": false, "multiple": false, @@ -235,142 +329,19 @@ "fields": null, "methods": null, "columns": null, - "label": "windows", + "label": "KUBERNETES", "fontSize": 16, "fontFamily": "DEFAULT", "language": "", - "color": "N1", + "color": "white", "italic": false, "bold": true, "underline": false, - "labelWidth": 64, + "labelWidth": 94, "labelHeight": 21, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, - "level": 2 - }, - { - "id": "todo root level grid.linux", - "type": "rectangle", - "pos": { - "x": 912, - "y": 552 - }, - "width": 800, - "height": 200, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "linux", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 35, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "todo root level grid.macos", - "type": "rectangle", - "pos": { - "x": 72, - "y": 792 - }, - "width": 800, - "height": 200, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "macos", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 45, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "todo root level grid.kubernetes", - "type": "rectangle", - "pos": { - "x": 912, - "y": 792 - }, - "width": 800, - "height": 200, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "B5", - "stroke": "B1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "kubernetes", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 80, - "labelHeight": 21, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 + "level": 1 } ], "connections": [], @@ -387,7 +358,7 @@ "strokeDash": 0, "strokeWidth": 0, "borderRadius": 0, - "fill": "N7", + "fill": "black", "stroke": "", "shadow": false, "3d": false, diff --git a/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg index 8ae60a5db..2e9ae781c 100644 --- a/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg @@ -1,17 +1,10 @@ -todo root level gridflowdagger engineany docker compatible runtimeany ciwindowslinuxmacoskubernetes - + .d2-1379472985 .fill-N1{fill:#0A0F25;} + .d2-1379472985 .fill-N2{fill:#676C7E;} + .d2-1379472985 .fill-N3{fill:#9499AB;} + .d2-1379472985 .fill-N4{fill:#CFD2DD;} + .d2-1379472985 .fill-N5{fill:#DEE1EB;} + .d2-1379472985 .fill-N6{fill:#EEF1F8;} + .d2-1379472985 .fill-N7{fill:#FFFFFF;} + .d2-1379472985 .fill-B1{fill:#0D32B2;} + .d2-1379472985 .fill-B2{fill:#0D32B2;} + .d2-1379472985 .fill-B3{fill:#E3E9FD;} + .d2-1379472985 .fill-B4{fill:#E3E9FD;} + .d2-1379472985 .fill-B5{fill:#EDF0FD;} + .d2-1379472985 .fill-B6{fill:#F7F8FE;} + .d2-1379472985 .fill-AA2{fill:#4A6FF3;} + .d2-1379472985 .fill-AA4{fill:#EDF0FD;} + .d2-1379472985 .fill-AA5{fill:#F7F8FE;} + .d2-1379472985 .fill-AB4{fill:#EDF0FD;} + .d2-1379472985 .fill-AB5{fill:#F7F8FE;} + .d2-1379472985 .stroke-N1{stroke:#0A0F25;} + .d2-1379472985 .stroke-N2{stroke:#676C7E;} + .d2-1379472985 .stroke-N3{stroke:#9499AB;} + .d2-1379472985 .stroke-N4{stroke:#CFD2DD;} + .d2-1379472985 .stroke-N5{stroke:#DEE1EB;} + .d2-1379472985 .stroke-N6{stroke:#EEF1F8;} + .d2-1379472985 .stroke-N7{stroke:#FFFFFF;} + .d2-1379472985 .stroke-B1{stroke:#0D32B2;} + .d2-1379472985 .stroke-B2{stroke:#0D32B2;} + .d2-1379472985 .stroke-B3{stroke:#E3E9FD;} + .d2-1379472985 .stroke-B4{stroke:#E3E9FD;} + .d2-1379472985 .stroke-B5{stroke:#EDF0FD;} + .d2-1379472985 .stroke-B6{stroke:#F7F8FE;} + .d2-1379472985 .stroke-AA2{stroke:#4A6FF3;} + .d2-1379472985 .stroke-AA4{stroke:#EDF0FD;} + .d2-1379472985 .stroke-AA5{stroke:#F7F8FE;} + .d2-1379472985 .stroke-AB4{stroke:#EDF0FD;} + .d2-1379472985 .stroke-AB5{stroke:#F7F8FE;} + .d2-1379472985 .background-color-N1{background-color:#0A0F25;} + .d2-1379472985 .background-color-N2{background-color:#676C7E;} + .d2-1379472985 .background-color-N3{background-color:#9499AB;} + .d2-1379472985 .background-color-N4{background-color:#CFD2DD;} + .d2-1379472985 .background-color-N5{background-color:#DEE1EB;} + .d2-1379472985 .background-color-N6{background-color:#EEF1F8;} + .d2-1379472985 .background-color-N7{background-color:#FFFFFF;} + .d2-1379472985 .background-color-B1{background-color:#0D32B2;} + .d2-1379472985 .background-color-B2{background-color:#0D32B2;} + .d2-1379472985 .background-color-B3{background-color:#E3E9FD;} + .d2-1379472985 .background-color-B4{background-color:#E3E9FD;} + .d2-1379472985 .background-color-B5{background-color:#EDF0FD;} + .d2-1379472985 .background-color-B6{background-color:#F7F8FE;} + .d2-1379472985 .background-color-AA2{background-color:#4A6FF3;} + .d2-1379472985 .background-color-AA4{background-color:#EDF0FD;} + .d2-1379472985 .background-color-AA5{background-color:#F7F8FE;} + .d2-1379472985 .background-color-AB4{background-color:#EDF0FD;} + .d2-1379472985 .background-color-AB5{background-color:#F7F8FE;} + .d2-1379472985 .color-N1{color:#0A0F25;} + .d2-1379472985 .color-N2{color:#676C7E;} + .d2-1379472985 .color-N3{color:#9499AB;} + .d2-1379472985 .color-N4{color:#CFD2DD;} + .d2-1379472985 .color-N5{color:#DEE1EB;} + .d2-1379472985 .color-N6{color:#EEF1F8;} + .d2-1379472985 .color-N7{color:#FFFFFF;} + .d2-1379472985 .color-B1{color:#0D32B2;} + .d2-1379472985 .color-B2{color:#0D32B2;} + .d2-1379472985 .color-B3{color:#E3E9FD;} + .d2-1379472985 .color-B4{color:#E3E9FD;} + .d2-1379472985 .color-B5{color:#EDF0FD;} + .d2-1379472985 .color-B6{color:#F7F8FE;} + .d2-1379472985 .color-AA2{color:#4A6FF3;} + .d2-1379472985 .color-AA4{color:#EDF0FD;} + .d2-1379472985 .color-AA5{color:#F7F8FE;} + .d2-1379472985 .color-AB4{color:#EDF0FD;} + .d2-1379472985 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES + \ No newline at end of file diff --git a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json index d1ba12de3..b9acb9863 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json @@ -8,10 +8,10 @@ "type": "rectangle", "pos": { "x": 0, - "y": 203 + "y": 204 }, "width": 272, - "height": 464, + "height": 461, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -90,10 +90,10 @@ "type": "rectangle", "pos": { "x": 1050, - "y": 263 + "y": 283 }, - "width": 764, - "height": 344, + "width": 584, + "height": 303, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -130,10 +130,10 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 2316, + "x": 2136, "y": 0 }, - "width": 920, + "width": 820, "height": 212, "opacity": 1, "strokeDash": 0, @@ -171,10 +171,10 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 2448, + "x": 2255, "y": 232 }, - "width": 656, + "width": 582, "height": 344, "opacity": 1, "strokeDash": 0, @@ -212,7 +212,7 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 2676, + "x": 2446, "y": 596 }, "width": 201, @@ -266,7 +266,7 @@ "type": "oval", "pos": { "x": 60, - "y": 263 + "y": 264 }, "width": 152, "height": 152, @@ -319,10 +319,10 @@ "type": "oval", "pos": { "x": 60, - "y": 455 + "y": 456 }, "width": 152, - "height": 152, + "height": 149, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -577,10 +577,10 @@ "type": "text", "pos": { "x": 1110, - "y": 323 + "y": 343 }, - "width": 302, - "height": 92, + "width": 122, + "height": 51, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -617,11 +617,11 @@ "id": "teleport.inp", "type": "text", "pos": { - "x": 1452, - "y": 323 + "x": 1272, + "y": 343 }, "width": 302, - "height": 92, + "height": 51, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -659,9 +659,9 @@ "type": "rectangle", "pos": { "x": 1110, - "y": 455 + "y": 434 }, - "width": 302, + "width": 212, "height": 92, "opacity": 1, "strokeDash": 0, @@ -711,10 +711,10 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 1452, - "y": 455 + "x": 1362, + "y": 434 }, - "width": 302, + "width": 212, "height": 92, "opacity": 1, "strokeDash": 0, @@ -764,10 +764,10 @@ "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 2376, + "x": 2196, "y": 60 }, - "width": 128, + "width": 110, "height": 92, "opacity": 1, "strokeDash": 0, @@ -817,7 +817,7 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 2544, + "x": 2346, "y": 60 }, "width": 128, @@ -858,10 +858,10 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 2712, + "x": 2514, "y": 60 }, - "width": 128, + "width": 72, "height": 92, "opacity": 1, "strokeDash": 0, @@ -899,10 +899,10 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 2880, + "x": 2626, "y": 60 }, - "width": 128, + "width": 119, "height": 92, "opacity": 1, "strokeDash": 0, @@ -940,10 +940,10 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 3048, + "x": 2785, "y": 60 }, - "width": 128, + "width": 111, "height": 92, "opacity": 1, "strokeDash": 0, @@ -993,10 +993,10 @@ "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 2508, + "x": 2315, "y": 292 }, - "width": 152, + "width": 108, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1046,7 +1046,7 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 2700, + "x": 2463, "y": 292 }, "width": 152, @@ -1099,10 +1099,10 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 2892, + "x": 2655, "y": 292 }, - "width": 152, + "width": 122, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1152,10 +1152,10 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 2508, + "x": 2315, "y": 424 }, - "width": 152, + "width": 138, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1205,10 +1205,10 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 2700, + "x": 2493, "y": 424 }, - "width": 152, + "width": 108, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1258,10 +1258,10 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 2892, + "x": 2641, "y": 424 }, - "width": 152, + "width": 136, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1434,19 +1434,19 @@ "labelPercentage": 0, "route": [ { - "x": 1763.433789954338, - "y": 262.5 + "x": 1592.4246575342465, + "y": 283 }, { - "x": 2004.6867579908676, - "y": 137.3 + "x": 1826.4849315068493, + "y": 141.4 }, { - "x": 2115.2, + "x": 1935.2, "y": 106 }, { - "x": 2316, + "x": 2136, "y": 106 } ], @@ -1483,19 +1483,19 @@ "labelPercentage": 0, "route": [ { - "x": 1814, - "y": 416.09399684044234 + "x": 1634, + "y": 418.0985267034991 }, { - "x": 2014.8, - "y": 406.41879936808846 + "x": 1834.8, + "y": 406.81970534069984 }, { - "x": 2141.6, + "x": 1959, "y": 404 }, { - "x": 2448, + "x": 2255, "y": 404 } ], @@ -1532,20 +1532,20 @@ "labelPercentage": 0, "route": [ { - "x": 1814, - "y": 510.2361769352291 + "x": 1634, + "y": 501.98802946593 }, { - "x": 2014.8, - "y": 550.0472353870458 + "x": 1834.8, + "y": 548.397605893186 }, { - "x": 2187.1, - "y": 576.3143459915611 + "x": 1997.1, + "y": 576.1111951588503 }, { - "x": 2675.5, - "y": 641.5717299578059 + "x": 2445.5, + "y": 640.5559757942511 } ], "isCurve": true, @@ -1581,20 +1581,20 @@ "labelPercentage": 0, "route": [ { - "x": 1814, - "y": 585.9723538704582 + "x": 1634, + "y": 569.47605893186 }, { - "x": 2014.8, - "y": 665.5944707740916 + "x": 1834.8, + "y": 662.295211786372 }, { - "x": 2187.1, - "y": 680.2622362869198 + "x": 1997.1, + "y": 680.3274583963691 }, { - "x": 2675.5, - "y": 659.3111814345991 + "x": 2445.5, + "y": 659.6372919818457 } ], "isCurve": true, diff --git a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg index f6a003864..8490082b2 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg @@ -1,23 +1,23 @@ -Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

-

Identity Native Proxy

-
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

+

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file diff --git a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json index 791027e81..bb00928e2 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json @@ -8,10 +8,10 @@ "type": "rectangle", "pos": { "x": 12, - "y": 190 + "y": 196 }, "width": 272, - "height": 464, + "height": 461, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -49,7 +49,7 @@ "type": "rectangle", "pos": { "x": 354, - "y": 117 + "y": 122 }, "width": 236, "height": 610, @@ -90,10 +90,10 @@ "type": "rectangle", "pos": { "x": 660, - "y": 250 + "y": 275 }, - "width": 764, - "height": 344, + "width": 584, + "height": 303, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -130,10 +130,10 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 2280, + "x": 2026, "y": 12 }, - "width": 920, + "width": 820, "height": 212, "opacity": 1, "strokeDash": 0, @@ -171,10 +171,10 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 1554, + "x": 1374, "y": 150 }, - "width": 656, + "width": 582, "height": 344, "opacity": 1, "strokeDash": 0, @@ -212,7 +212,7 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 1554, + "x": 1374, "y": 514 }, "width": 201, @@ -266,7 +266,7 @@ "type": "oval", "pos": { "x": 72, - "y": 250 + "y": 256 }, "width": 152, "height": 152, @@ -319,10 +319,10 @@ "type": "oval", "pos": { "x": 72, - "y": 442 + "y": 448 }, "width": 152, - "height": 152, + "height": 149, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -372,7 +372,7 @@ "type": "rectangle", "pos": { "x": 414, - "y": 177 + "y": 182 }, "width": 116, "height": 66, @@ -413,7 +413,7 @@ "type": "rectangle", "pos": { "x": 414, - "y": 283 + "y": 288 }, "width": 116, "height": 66, @@ -454,7 +454,7 @@ "type": "rectangle", "pos": { "x": 414, - "y": 389 + "y": 394 }, "width": 116, "height": 66, @@ -495,7 +495,7 @@ "type": "rectangle", "pos": { "x": 414, - "y": 495 + "y": 500 }, "width": 116, "height": 66, @@ -536,7 +536,7 @@ "type": "rectangle", "pos": { "x": 414, - "y": 601 + "y": 606 }, "width": 116, "height": 66, @@ -577,10 +577,10 @@ "type": "text", "pos": { "x": 720, - "y": 310 + "y": 335 }, - "width": 302, - "height": 92, + "width": 122, + "height": 51, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -617,11 +617,11 @@ "id": "teleport.inp", "type": "text", "pos": { - "x": 1062, - "y": 310 + "x": 882, + "y": 335 }, "width": 302, - "height": 92, + "height": 51, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -659,9 +659,9 @@ "type": "rectangle", "pos": { "x": 720, - "y": 442 + "y": 426 }, - "width": 302, + "width": 212, "height": 92, "opacity": 1, "strokeDash": 0, @@ -711,10 +711,10 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 1062, - "y": 442 + "x": 972, + "y": 426 }, - "width": 302, + "width": 212, "height": 92, "opacity": 1, "strokeDash": 0, @@ -764,10 +764,10 @@ "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 2340, + "x": 2086, "y": 72 }, - "width": 128, + "width": 110, "height": 92, "opacity": 1, "strokeDash": 0, @@ -817,7 +817,7 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 2508, + "x": 2236, "y": 72 }, "width": 128, @@ -858,10 +858,10 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 2676, + "x": 2404, "y": 72 }, - "width": 128, + "width": 72, "height": 92, "opacity": 1, "strokeDash": 0, @@ -899,10 +899,10 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 2844, + "x": 2516, "y": 72 }, - "width": 128, + "width": 119, "height": 92, "opacity": 1, "strokeDash": 0, @@ -940,10 +940,10 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 3012, + "x": 2675, "y": 72 }, - "width": 128, + "width": 111, "height": 92, "opacity": 1, "strokeDash": 0, @@ -993,10 +993,10 @@ "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 1614, + "x": 1434, "y": 210 }, - "width": 152, + "width": 108, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1046,7 +1046,7 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 1806, + "x": 1582, "y": 210 }, "width": 152, @@ -1099,10 +1099,10 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 1998, + "x": 1774, "y": 210 }, - "width": 152, + "width": 122, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1152,10 +1152,10 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 1614, + "x": 1434, "y": 342 }, - "width": 152, + "width": 138, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1205,10 +1205,10 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 1806, + "x": 1612, "y": 342 }, - "width": 152, + "width": 108, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1258,10 +1258,10 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 1998, + "x": 1760, "y": 342 }, - "width": 152, + "width": 136, "height": 92, "opacity": 1, "strokeDash": 0, @@ -1337,11 +1337,11 @@ "route": [ { "x": 284, - "y": 422.93333333333334 + "y": 427.0333333333333 }, { "x": 354, - "y": 422.93333333333334 + "y": 427.0333333333333 } ], "animated": false, @@ -1377,11 +1377,11 @@ "route": [ { "x": 590, - "y": 422.93333333333334 + "y": 427.0333333333333 }, { "x": 660, - "y": 422.93333333333334 + "y": 427.0333333333333 } ], "animated": false, @@ -1416,19 +1416,19 @@ "labelPercentage": 0, "route": [ { - "x": 1424, - "y": 319.73333333333335 + "x": 1244, + "y": 336.1333333333333 }, { - "x": 1464, - "y": 319.73333333333335 + "x": 1284, + "y": 336.1333333333333 }, { - "x": 1464, + "x": 1284, "y": 118 }, { - "x": 2280, + "x": 2026, "y": 118 } ], @@ -1464,12 +1464,12 @@ "labelPercentage": 0, "route": [ { - "x": 1424, - "y": 388.53333333333336 + "x": 1244, + "y": 396.7333333333333 }, { - "x": 1554, - "y": 388.53333333333336 + "x": 1374, + "y": 396.7333333333333 } ], "animated": false, @@ -1504,19 +1504,19 @@ "labelPercentage": 0, "route": [ { - "x": 1424, + "x": 1244, "y": 457.3333333333333 }, { - "x": 1514, + "x": 1334, "y": 457.3333333333333 }, { - "x": 1514, + "x": 1334, "y": 553.3333333333333 }, { - "x": 1554, + "x": 1374, "y": 553.3333333333333 } ], @@ -1552,20 +1552,20 @@ "labelPercentage": 0, "route": [ { - "x": 1424, - "y": 526.1333333333333 + "x": 1244, + "y": 517.9333333333333 }, { - "x": 1464, - "y": 526.1333333333333 + "x": 1284, + "y": 517.9333333333333 }, { - "x": 1464, - "y": 592.6666666666667 + "x": 1284, + "y": 592.6666666666666 }, { - "x": 1554, - "y": 592.6666666666667 + "x": 1374, + "y": 592.6666666666666 } ], "animated": false, diff --git a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg index 1d5730d9b..0f29b7d25 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg @@ -1,23 +1,23 @@ -Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

-

Identity Native Proxy

-
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

+

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file From a16924752d57b42f5ad57034809f4b3ac9c4203c Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 11:38:33 -0700 Subject: [PATCH 12/31] finish column logic --- d2layouts/d2grid/layout.go | 76 +++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 755146535..180ae0cf2 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -135,15 +135,15 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { } } else { targetHeight := totalHeight / float64(grid.columns) - columnHeight := 0. - columnIndex := 0 + colHeight := 0. + colIndex := 0 for i, n := range grid.nodes { - layout[columnIndex] = append(layout[columnIndex], i) - columnHeight += n.Height + VERTICAL_PAD - if columnHeight > targetHeight && i < len(grid.nodes)-1 { + layout[colIndex] = append(layout[colIndex], i) + colHeight += n.Height + VERTICAL_PAD + if colHeight > targetHeight && i < len(grid.nodes)-1 { layout = append(layout, []int{}) - columnIndex++ - columnHeight = 0 + colIndex++ + colHeight = 0 } } } @@ -260,24 +260,27 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { // . └───┴──────────┘ │ │ // . │ ││ // . └─────────┴┘ + colHeights := []float64{} for _, column := range layout { - columnWidth := 0. + colWidth := 0. for _, nodeIndex := range column { n := grid.nodes[nodeIndex] n.TopLeft = cursor.Copy() cursor.Y += n.Height + VERTICAL_PAD - columnWidth = math.Max(columnWidth, n.Width) + colWidth = math.Max(colWidth, n.Width) } - maxY = math.Max(maxY, cursor.Y-VERTICAL_PAD) + colHeight := cursor.Y - VERTICAL_PAD + colHeights = append(colHeights, colHeight) + maxY = math.Max(maxY, colHeight) // set all nodes in column to the same width for _, nodeIndex := range column { n := grid.nodes[nodeIndex] - n.Width = columnWidth + n.Width = colWidth } // new column cursor.Y = 0 - cursor.X += columnWidth + HORIZONTAL_PAD + cursor.X += colWidth + HORIZONTAL_PAD } maxX = cursor.X - HORIZONTAL_PAD // then expand shortest nodes to make each column the same height @@ -291,7 +294,54 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { // . │ │ │ │ │ │ // . │ │ │ │ │ │ // . └──────────────┘ └──────────┘ └─────────────────┘ - // TODO see rows + for i, column := range layout { + colHeight := colHeights[i] + if colHeight == maxY { + continue + } + delta := maxY - colHeight + nodes := []*d2graph.Object{} + var tallest float64 + for _, nodeIndex := range column { + n := grid.nodes[nodeIndex] + tallest = math.Max(tallest, n.Height) + nodes = append(nodes, n) + } + sort.Slice(nodes, func(i, j int) bool { + return nodes[i].Height < nodes[j].Height + }) + // expand smaller nodes to fill remaining space + for _, n := range nodes { + if n.Height < tallest { + var index int + for i, nodeIndex := range column { + if n == grid.nodes[nodeIndex] { + index = i + break + } + } + grow := math.Min(tallest-n.Height, delta) + n.Height += grow + // shift following nodes + for i := index + 1; i < len(column); i++ { + grid.nodes[column[i]].TopLeft.Y += grow + } + delta -= grow + if delta <= 0 { + break + } + } + } + if delta > 0 { + grow := delta / float64(len(column)) + for i := len(column) - 1; i >= 0; i-- { + n := grid.nodes[column[i]] + n.TopLeft.Y += grow * float64(i) + n.Height += grow + delta -= grow + } + } + } } grid.width = maxX grid.height = maxY From 7ac72140c7178c723f8e68163d952acee70761ba Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 13:42:25 -0700 Subject: [PATCH 13/31] fixing rows creation --- d2layouts/d2grid/layout.go | 57 +++++++++++++++++++++----- e2etests/testdata/files/dagger_grid.d2 | 46 +++++++++++++++++---- 2 files changed, 85 insertions(+), 18 deletions(-) diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 180ae0cf2..c16529fe0 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -123,27 +123,62 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { targetWidth := totalWidth / float64(grid.rows) rowWidth := 0. rowIndex := 0 - for i, n := range grid.nodes { + addRow := func() { + layout = append(layout, []int{}) + rowIndex++ + rowWidth = 0 + } + addNode := func(i int, n *d2graph.Object) { layout[rowIndex] = append(layout[rowIndex], i) rowWidth += n.Width + HORIZONTAL_PAD - // add a new row if we pass the target width and there are more nodes - if rowWidth > targetWidth && i < len(grid.nodes)-1 { - layout = append(layout, []int{}) - rowIndex++ - rowWidth = 0 + } + + for i, n := range grid.nodes { + // if the next node will be past the target, start a new row + if rowWidth+n.Width+HORIZONTAL_PAD > targetWidth { + // if the node is mostly past the target, put it on the next row + if rowWidth+n.Width/2 > targetWidth { + addRow() + addNode(i, n) + } else { + addNode(i, n) + if i < len(grid.nodes)-1 { + addRow() + } + } + } else { + addNode(i, n) } } } else { targetHeight := totalHeight / float64(grid.columns) colHeight := 0. colIndex := 0 - for i, n := range grid.nodes { + addCol := func() { + layout = append(layout, []int{}) + colIndex++ + colHeight = 0 + } + addNode := func(i int, n *d2graph.Object) { layout[colIndex] = append(layout[colIndex], i) colHeight += n.Height + VERTICAL_PAD - if colHeight > targetHeight && i < len(grid.nodes)-1 { - layout = append(layout, []int{}) - colIndex++ - colHeight = 0 + } + + for i, n := range grid.nodes { + // if the next node will be past the target, start a new row + if colHeight+n.Height+VERTICAL_PAD > targetHeight { + // if the node is mostly past the target, put it on the next row + if colHeight+n.Height/2 > targetHeight { + addCol() + addNode(i, n) + } else { + addNode(i, n) + if i < len(grid.nodes)-1 { + addCol() + } + } + } else { + addNode(i, n) } } } diff --git a/e2etests/testdata/files/dagger_grid.d2 b/e2etests/testdata/files/dagger_grid.d2 index b3db8ac9a..9bbe12df2 100644 --- a/e2etests/testdata/files/dagger_grid.d2 +++ b/e2etests/testdata/files/dagger_grid.d2 @@ -1,12 +1,44 @@ -rows: 4 +rows: 5 style.fill: black -flow: "" { - width: 800 - height: 200 - style: { - fill: cornflowerblue - } +flow1: "" { + width: 120 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow2: "" { + width: 120 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow3: "" { + width: 120 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow4: "" { + width: 120 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow5: "" { + width: 120 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow6: "" { + width: 240 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow7: "" { + width: 100 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow8: "" { + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow9: "" { + width: 120 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} +} +flow10: "" { + width: 120 + style: {fill: white; stroke: cornflowerblue; stroke-width: 10} } DAGGER ENGINE: { From a9a7d23ffdcca42b20eb9b4c61afcb4bf4abc3b1 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 13:45:16 -0700 Subject: [PATCH 14/31] update test --- .../stable/dagger_grid/dagre/board.exp.json | 409 +++++++++++++++++- .../stable/dagger_grid/dagre/sketch.exp.svg | 154 +++---- .../stable/dagger_grid/elk/board.exp.json | 409 +++++++++++++++++- .../stable/dagger_grid/elk/sketch.exp.svg | 154 +++---- 4 files changed, 932 insertions(+), 194 deletions(-) diff --git a/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json index b438f9716..e8cca26bb 100644 --- a/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json @@ -4,20 +4,389 @@ "fontFamily": "SourceSansPro", "shapes": [ { - "id": "flow", + "id": "flow1", "type": "rectangle", "pos": { "x": 0, "y": 0 }, - "width": 800, - "height": 200, + "width": 136, + "height": 100, "opacity": 1, "strokeDash": 0, - "strokeWidth": 2, + "strokeWidth": 10, "borderRadius": 0, - "fill": "cornflowerblue", - "stroke": "B1", + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow2", + "type": "rectangle", + "pos": { + "x": 176, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow3", + "type": "rectangle", + "pos": { + "x": 352, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow4", + "type": "rectangle", + "pos": { + "x": 528, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow5", + "type": "rectangle", + "pos": { + "x": 704, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow6", + "type": "rectangle", + "pos": { + "x": 0, + "y": 140 + }, + "width": 240, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow7", + "type": "rectangle", + "pos": { + "x": 280, + "y": 140 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow8", + "type": "rectangle", + "pos": { + "x": 420, + "y": 140 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow9", + "type": "rectangle", + "pos": { + "x": 560, + "y": 140 + }, + "width": 120, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow10", + "type": "rectangle", + "pos": { + "x": 720, + "y": 140 + }, + "width": 120, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", "shadow": false, "3d": false, "multiple": false, @@ -49,9 +418,9 @@ "type": "rectangle", "pos": { "x": 0, - "y": 240 + "y": 280 }, - "width": 800, + "width": 840, "height": 61, "opacity": 1, "strokeDash": 0, @@ -90,9 +459,9 @@ "type": "rectangle", "pos": { "x": 0, - "y": 341 + "y": 381 }, - "width": 800, + "width": 840, "height": 87, "opacity": 1, "strokeDash": 0, @@ -143,7 +512,7 @@ "type": "rectangle", "pos": { "x": 0, - "y": 468 + "y": 508 }, "width": 139, "height": 66, @@ -184,9 +553,9 @@ "type": "rectangle", "pos": { "x": 179, - "y": 468 + "y": 508 }, - "width": 117, + "width": 124, "height": 66, "opacity": 1, "strokeDash": 0, @@ -224,8 +593,8 @@ "id": "LINUX", "type": "rectangle", "pos": { - "x": 336, - "y": 468 + "x": 343, + "y": 508 }, "width": 139, "height": 66, @@ -265,10 +634,10 @@ "id": "MACOS", "type": "rectangle", "pos": { - "x": 515, - "y": 468 + "x": 522, + "y": 508 }, - "width": 106, + "width": 139, "height": 66, "opacity": 1, "strokeDash": 0, @@ -306,8 +675,8 @@ "id": "KUBERNETES", "type": "rectangle", "pos": { - "x": 661, - "y": 468 + "x": 701, + "y": 508 }, "width": 139, "height": 66, diff --git a/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg index 2e9ae781c..9841e85d6 100644 --- a/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg @@ -1,9 +1,9 @@ -DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES - + .d2-1905618427 .fill-N1{fill:#0A0F25;} + .d2-1905618427 .fill-N2{fill:#676C7E;} + .d2-1905618427 .fill-N3{fill:#9499AB;} + .d2-1905618427 .fill-N4{fill:#CFD2DD;} + .d2-1905618427 .fill-N5{fill:#DEE1EB;} + .d2-1905618427 .fill-N6{fill:#EEF1F8;} + .d2-1905618427 .fill-N7{fill:#FFFFFF;} + .d2-1905618427 .fill-B1{fill:#0D32B2;} + .d2-1905618427 .fill-B2{fill:#0D32B2;} + .d2-1905618427 .fill-B3{fill:#E3E9FD;} + .d2-1905618427 .fill-B4{fill:#E3E9FD;} + .d2-1905618427 .fill-B5{fill:#EDF0FD;} + .d2-1905618427 .fill-B6{fill:#F7F8FE;} + .d2-1905618427 .fill-AA2{fill:#4A6FF3;} + .d2-1905618427 .fill-AA4{fill:#EDF0FD;} + .d2-1905618427 .fill-AA5{fill:#F7F8FE;} + .d2-1905618427 .fill-AB4{fill:#EDF0FD;} + .d2-1905618427 .fill-AB5{fill:#F7F8FE;} + .d2-1905618427 .stroke-N1{stroke:#0A0F25;} + .d2-1905618427 .stroke-N2{stroke:#676C7E;} + .d2-1905618427 .stroke-N3{stroke:#9499AB;} + .d2-1905618427 .stroke-N4{stroke:#CFD2DD;} + .d2-1905618427 .stroke-N5{stroke:#DEE1EB;} + .d2-1905618427 .stroke-N6{stroke:#EEF1F8;} + .d2-1905618427 .stroke-N7{stroke:#FFFFFF;} + .d2-1905618427 .stroke-B1{stroke:#0D32B2;} + .d2-1905618427 .stroke-B2{stroke:#0D32B2;} + .d2-1905618427 .stroke-B3{stroke:#E3E9FD;} + .d2-1905618427 .stroke-B4{stroke:#E3E9FD;} + .d2-1905618427 .stroke-B5{stroke:#EDF0FD;} + .d2-1905618427 .stroke-B6{stroke:#F7F8FE;} + .d2-1905618427 .stroke-AA2{stroke:#4A6FF3;} + .d2-1905618427 .stroke-AA4{stroke:#EDF0FD;} + .d2-1905618427 .stroke-AA5{stroke:#F7F8FE;} + .d2-1905618427 .stroke-AB4{stroke:#EDF0FD;} + .d2-1905618427 .stroke-AB5{stroke:#F7F8FE;} + .d2-1905618427 .background-color-N1{background-color:#0A0F25;} + .d2-1905618427 .background-color-N2{background-color:#676C7E;} + .d2-1905618427 .background-color-N3{background-color:#9499AB;} + .d2-1905618427 .background-color-N4{background-color:#CFD2DD;} + .d2-1905618427 .background-color-N5{background-color:#DEE1EB;} + .d2-1905618427 .background-color-N6{background-color:#EEF1F8;} + .d2-1905618427 .background-color-N7{background-color:#FFFFFF;} + .d2-1905618427 .background-color-B1{background-color:#0D32B2;} + .d2-1905618427 .background-color-B2{background-color:#0D32B2;} + .d2-1905618427 .background-color-B3{background-color:#E3E9FD;} + .d2-1905618427 .background-color-B4{background-color:#E3E9FD;} + .d2-1905618427 .background-color-B5{background-color:#EDF0FD;} + .d2-1905618427 .background-color-B6{background-color:#F7F8FE;} + .d2-1905618427 .background-color-AA2{background-color:#4A6FF3;} + .d2-1905618427 .background-color-AA4{background-color:#EDF0FD;} + .d2-1905618427 .background-color-AA5{background-color:#F7F8FE;} + .d2-1905618427 .background-color-AB4{background-color:#EDF0FD;} + .d2-1905618427 .background-color-AB5{background-color:#F7F8FE;} + .d2-1905618427 .color-N1{color:#0A0F25;} + .d2-1905618427 .color-N2{color:#676C7E;} + .d2-1905618427 .color-N3{color:#9499AB;} + .d2-1905618427 .color-N4{color:#CFD2DD;} + .d2-1905618427 .color-N5{color:#DEE1EB;} + .d2-1905618427 .color-N6{color:#EEF1F8;} + .d2-1905618427 .color-N7{color:#FFFFFF;} + .d2-1905618427 .color-B1{color:#0D32B2;} + .d2-1905618427 .color-B2{color:#0D32B2;} + .d2-1905618427 .color-B3{color:#E3E9FD;} + .d2-1905618427 .color-B4{color:#E3E9FD;} + .d2-1905618427 .color-B5{color:#EDF0FD;} + .d2-1905618427 .color-B6{color:#F7F8FE;} + .d2-1905618427 .color-AA2{color:#4A6FF3;} + .d2-1905618427 .color-AA4{color:#EDF0FD;} + .d2-1905618427 .color-AA5{color:#F7F8FE;} + .d2-1905618427 .color-AB4{color:#EDF0FD;} + .d2-1905618427 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES + \ No newline at end of file diff --git a/e2etests/testdata/stable/dagger_grid/elk/board.exp.json b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json index b438f9716..e8cca26bb 100644 --- a/e2etests/testdata/stable/dagger_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json @@ -4,20 +4,389 @@ "fontFamily": "SourceSansPro", "shapes": [ { - "id": "flow", + "id": "flow1", "type": "rectangle", "pos": { "x": 0, "y": 0 }, - "width": 800, - "height": 200, + "width": 136, + "height": 100, "opacity": 1, "strokeDash": 0, - "strokeWidth": 2, + "strokeWidth": 10, "borderRadius": 0, - "fill": "cornflowerblue", - "stroke": "B1", + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow2", + "type": "rectangle", + "pos": { + "x": 176, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow3", + "type": "rectangle", + "pos": { + "x": 352, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow4", + "type": "rectangle", + "pos": { + "x": 528, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow5", + "type": "rectangle", + "pos": { + "x": 704, + "y": 0 + }, + "width": 136, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow6", + "type": "rectangle", + "pos": { + "x": 0, + "y": 140 + }, + "width": 240, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow7", + "type": "rectangle", + "pos": { + "x": 280, + "y": 140 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow8", + "type": "rectangle", + "pos": { + "x": 420, + "y": 140 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow9", + "type": "rectangle", + "pos": { + "x": 560, + "y": 140 + }, + "width": 120, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "flow10", + "type": "rectangle", + "pos": { + "x": 720, + "y": 140 + }, + "width": 120, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 10, + "borderRadius": 0, + "fill": "white", + "stroke": "cornflowerblue", "shadow": false, "3d": false, "multiple": false, @@ -49,9 +418,9 @@ "type": "rectangle", "pos": { "x": 0, - "y": 240 + "y": 280 }, - "width": 800, + "width": 840, "height": 61, "opacity": 1, "strokeDash": 0, @@ -90,9 +459,9 @@ "type": "rectangle", "pos": { "x": 0, - "y": 341 + "y": 381 }, - "width": 800, + "width": 840, "height": 87, "opacity": 1, "strokeDash": 0, @@ -143,7 +512,7 @@ "type": "rectangle", "pos": { "x": 0, - "y": 468 + "y": 508 }, "width": 139, "height": 66, @@ -184,9 +553,9 @@ "type": "rectangle", "pos": { "x": 179, - "y": 468 + "y": 508 }, - "width": 117, + "width": 124, "height": 66, "opacity": 1, "strokeDash": 0, @@ -224,8 +593,8 @@ "id": "LINUX", "type": "rectangle", "pos": { - "x": 336, - "y": 468 + "x": 343, + "y": 508 }, "width": 139, "height": 66, @@ -265,10 +634,10 @@ "id": "MACOS", "type": "rectangle", "pos": { - "x": 515, - "y": 468 + "x": 522, + "y": 508 }, - "width": 106, + "width": 139, "height": 66, "opacity": 1, "strokeDash": 0, @@ -306,8 +675,8 @@ "id": "KUBERNETES", "type": "rectangle", "pos": { - "x": 661, - "y": 468 + "x": 701, + "y": 508 }, "width": 139, "height": 66, diff --git a/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg index 2e9ae781c..9841e85d6 100644 --- a/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg @@ -1,9 +1,9 @@ -DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES - + .d2-1905618427 .fill-N1{fill:#0A0F25;} + .d2-1905618427 .fill-N2{fill:#676C7E;} + .d2-1905618427 .fill-N3{fill:#9499AB;} + .d2-1905618427 .fill-N4{fill:#CFD2DD;} + .d2-1905618427 .fill-N5{fill:#DEE1EB;} + .d2-1905618427 .fill-N6{fill:#EEF1F8;} + .d2-1905618427 .fill-N7{fill:#FFFFFF;} + .d2-1905618427 .fill-B1{fill:#0D32B2;} + .d2-1905618427 .fill-B2{fill:#0D32B2;} + .d2-1905618427 .fill-B3{fill:#E3E9FD;} + .d2-1905618427 .fill-B4{fill:#E3E9FD;} + .d2-1905618427 .fill-B5{fill:#EDF0FD;} + .d2-1905618427 .fill-B6{fill:#F7F8FE;} + .d2-1905618427 .fill-AA2{fill:#4A6FF3;} + .d2-1905618427 .fill-AA4{fill:#EDF0FD;} + .d2-1905618427 .fill-AA5{fill:#F7F8FE;} + .d2-1905618427 .fill-AB4{fill:#EDF0FD;} + .d2-1905618427 .fill-AB5{fill:#F7F8FE;} + .d2-1905618427 .stroke-N1{stroke:#0A0F25;} + .d2-1905618427 .stroke-N2{stroke:#676C7E;} + .d2-1905618427 .stroke-N3{stroke:#9499AB;} + .d2-1905618427 .stroke-N4{stroke:#CFD2DD;} + .d2-1905618427 .stroke-N5{stroke:#DEE1EB;} + .d2-1905618427 .stroke-N6{stroke:#EEF1F8;} + .d2-1905618427 .stroke-N7{stroke:#FFFFFF;} + .d2-1905618427 .stroke-B1{stroke:#0D32B2;} + .d2-1905618427 .stroke-B2{stroke:#0D32B2;} + .d2-1905618427 .stroke-B3{stroke:#E3E9FD;} + .d2-1905618427 .stroke-B4{stroke:#E3E9FD;} + .d2-1905618427 .stroke-B5{stroke:#EDF0FD;} + .d2-1905618427 .stroke-B6{stroke:#F7F8FE;} + .d2-1905618427 .stroke-AA2{stroke:#4A6FF3;} + .d2-1905618427 .stroke-AA4{stroke:#EDF0FD;} + .d2-1905618427 .stroke-AA5{stroke:#F7F8FE;} + .d2-1905618427 .stroke-AB4{stroke:#EDF0FD;} + .d2-1905618427 .stroke-AB5{stroke:#F7F8FE;} + .d2-1905618427 .background-color-N1{background-color:#0A0F25;} + .d2-1905618427 .background-color-N2{background-color:#676C7E;} + .d2-1905618427 .background-color-N3{background-color:#9499AB;} + .d2-1905618427 .background-color-N4{background-color:#CFD2DD;} + .d2-1905618427 .background-color-N5{background-color:#DEE1EB;} + .d2-1905618427 .background-color-N6{background-color:#EEF1F8;} + .d2-1905618427 .background-color-N7{background-color:#FFFFFF;} + .d2-1905618427 .background-color-B1{background-color:#0D32B2;} + .d2-1905618427 .background-color-B2{background-color:#0D32B2;} + .d2-1905618427 .background-color-B3{background-color:#E3E9FD;} + .d2-1905618427 .background-color-B4{background-color:#E3E9FD;} + .d2-1905618427 .background-color-B5{background-color:#EDF0FD;} + .d2-1905618427 .background-color-B6{background-color:#F7F8FE;} + .d2-1905618427 .background-color-AA2{background-color:#4A6FF3;} + .d2-1905618427 .background-color-AA4{background-color:#EDF0FD;} + .d2-1905618427 .background-color-AA5{background-color:#F7F8FE;} + .d2-1905618427 .background-color-AB4{background-color:#EDF0FD;} + .d2-1905618427 .background-color-AB5{background-color:#F7F8FE;} + .d2-1905618427 .color-N1{color:#0A0F25;} + .d2-1905618427 .color-N2{color:#676C7E;} + .d2-1905618427 .color-N3{color:#9499AB;} + .d2-1905618427 .color-N4{color:#CFD2DD;} + .d2-1905618427 .color-N5{color:#DEE1EB;} + .d2-1905618427 .color-N6{color:#EEF1F8;} + .d2-1905618427 .color-N7{color:#FFFFFF;} + .d2-1905618427 .color-B1{color:#0D32B2;} + .d2-1905618427 .color-B2{color:#0D32B2;} + .d2-1905618427 .color-B3{color:#E3E9FD;} + .d2-1905618427 .color-B4{color:#E3E9FD;} + .d2-1905618427 .color-B5{color:#EDF0FD;} + .d2-1905618427 .color-B6{color:#F7F8FE;} + .d2-1905618427 .color-AA2{color:#4A6FF3;} + .d2-1905618427 .color-AA4{color:#EDF0FD;} + .d2-1905618427 .color-AA5{color:#F7F8FE;} + .d2-1905618427 .color-AB4{color:#EDF0FD;} + .d2-1905618427 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES + \ No newline at end of file From bcc4ce1e923adaac0390f9f3162a287b38380633 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 13:47:51 -0700 Subject: [PATCH 15/31] update test --- e2etests/testdata/files/dagger_grid.d2 | 9 +- .../stable/dagger_grid/dagre/board.exp.json | 83 +++------- .../stable/dagger_grid/dagre/sketch.exp.svg | 154 +++++++++--------- .../stable/dagger_grid/elk/board.exp.json | 83 +++------- .../stable/dagger_grid/elk/sketch.exp.svg | 154 +++++++++--------- 5 files changed, 199 insertions(+), 284 deletions(-) diff --git a/e2etests/testdata/files/dagger_grid.d2 b/e2etests/testdata/files/dagger_grid.d2 index 9bbe12df2..dc9d8debe 100644 --- a/e2etests/testdata/files/dagger_grid.d2 +++ b/e2etests/testdata/files/dagger_grid.d2 @@ -26,18 +26,15 @@ flow6: "" { style: {fill: white; stroke: cornflowerblue; stroke-width: 10} } flow7: "" { - width: 100 + width: 80 style: {fill: white; stroke: cornflowerblue; stroke-width: 10} } flow8: "" { + width: 160 style: {fill: white; stroke: cornflowerblue; stroke-width: 10} } flow9: "" { - width: 120 - style: {fill: white; stroke: cornflowerblue; stroke-width: 10} -} -flow10: "" { - width: 120 + width: 160 style: {fill: white; stroke: cornflowerblue; stroke-width: 10} } diff --git a/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json index e8cca26bb..b94be0069 100644 --- a/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/dagger_grid/dagre/board.exp.json @@ -10,7 +10,7 @@ "x": 0, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -48,10 +48,10 @@ "id": "flow2", "type": "rectangle", "pos": { - "x": 176, + "x": 168, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -89,10 +89,10 @@ "id": "flow3", "type": "rectangle", "pos": { - "x": 352, + "x": 336, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -130,10 +130,10 @@ "id": "flow4", "type": "rectangle", "pos": { - "x": 528, + "x": 504, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -171,10 +171,10 @@ "id": "flow5", "type": "rectangle", "pos": { - "x": 704, + "x": 672, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -256,7 +256,7 @@ "x": 280, "y": 140 }, - "width": 100, + "width": 120, "height": 100, "opacity": 1, "strokeDash": 0, @@ -294,10 +294,10 @@ "id": "flow8", "type": "rectangle", "pos": { - "x": 420, + "x": 440, "y": 140 }, - "width": 100, + "width": 160, "height": 100, "opacity": 1, "strokeDash": 0, @@ -335,51 +335,10 @@ "id": "flow9", "type": "rectangle", "pos": { - "x": 560, + "x": 640, "y": 140 }, - "width": 120, - "height": 100, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 10, - "borderRadius": 0, - "fill": "white", - "stroke": "cornflowerblue", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 0, - "labelHeight": 0, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 1 - }, - { - "id": "flow10", - "type": "rectangle", - "pos": { - "x": 720, - "y": 140 - }, - "width": 120, + "width": 160, "height": 100, "opacity": 1, "strokeDash": 0, @@ -420,7 +379,7 @@ "x": 0, "y": 280 }, - "width": 840, + "width": 800, "height": 61, "opacity": 1, "strokeDash": 0, @@ -461,7 +420,7 @@ "x": 0, "y": 381 }, - "width": 840, + "width": 800, "height": 87, "opacity": 1, "strokeDash": 0, @@ -555,7 +514,7 @@ "x": 179, "y": 508 }, - "width": 124, + "width": 117, "height": 66, "opacity": 1, "strokeDash": 0, @@ -593,7 +552,7 @@ "id": "LINUX", "type": "rectangle", "pos": { - "x": 343, + "x": 336, "y": 508 }, "width": 139, @@ -634,10 +593,10 @@ "id": "MACOS", "type": "rectangle", "pos": { - "x": 522, + "x": 515, "y": 508 }, - "width": 139, + "width": 106, "height": 66, "opacity": 1, "strokeDash": 0, @@ -675,7 +634,7 @@ "id": "KUBERNETES", "type": "rectangle", "pos": { - "x": 701, + "x": 661, "y": 508 }, "width": 139, diff --git a/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg index 9841e85d6..cc62b273b 100644 --- a/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/dagger_grid/dagre/sketch.exp.svg @@ -1,9 +1,9 @@ -DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES - + .d2-1659554808 .fill-N1{fill:#0A0F25;} + .d2-1659554808 .fill-N2{fill:#676C7E;} + .d2-1659554808 .fill-N3{fill:#9499AB;} + .d2-1659554808 .fill-N4{fill:#CFD2DD;} + .d2-1659554808 .fill-N5{fill:#DEE1EB;} + .d2-1659554808 .fill-N6{fill:#EEF1F8;} + .d2-1659554808 .fill-N7{fill:#FFFFFF;} + .d2-1659554808 .fill-B1{fill:#0D32B2;} + .d2-1659554808 .fill-B2{fill:#0D32B2;} + .d2-1659554808 .fill-B3{fill:#E3E9FD;} + .d2-1659554808 .fill-B4{fill:#E3E9FD;} + .d2-1659554808 .fill-B5{fill:#EDF0FD;} + .d2-1659554808 .fill-B6{fill:#F7F8FE;} + .d2-1659554808 .fill-AA2{fill:#4A6FF3;} + .d2-1659554808 .fill-AA4{fill:#EDF0FD;} + .d2-1659554808 .fill-AA5{fill:#F7F8FE;} + .d2-1659554808 .fill-AB4{fill:#EDF0FD;} + .d2-1659554808 .fill-AB5{fill:#F7F8FE;} + .d2-1659554808 .stroke-N1{stroke:#0A0F25;} + .d2-1659554808 .stroke-N2{stroke:#676C7E;} + .d2-1659554808 .stroke-N3{stroke:#9499AB;} + .d2-1659554808 .stroke-N4{stroke:#CFD2DD;} + .d2-1659554808 .stroke-N5{stroke:#DEE1EB;} + .d2-1659554808 .stroke-N6{stroke:#EEF1F8;} + .d2-1659554808 .stroke-N7{stroke:#FFFFFF;} + .d2-1659554808 .stroke-B1{stroke:#0D32B2;} + .d2-1659554808 .stroke-B2{stroke:#0D32B2;} + .d2-1659554808 .stroke-B3{stroke:#E3E9FD;} + .d2-1659554808 .stroke-B4{stroke:#E3E9FD;} + .d2-1659554808 .stroke-B5{stroke:#EDF0FD;} + .d2-1659554808 .stroke-B6{stroke:#F7F8FE;} + .d2-1659554808 .stroke-AA2{stroke:#4A6FF3;} + .d2-1659554808 .stroke-AA4{stroke:#EDF0FD;} + .d2-1659554808 .stroke-AA5{stroke:#F7F8FE;} + .d2-1659554808 .stroke-AB4{stroke:#EDF0FD;} + .d2-1659554808 .stroke-AB5{stroke:#F7F8FE;} + .d2-1659554808 .background-color-N1{background-color:#0A0F25;} + .d2-1659554808 .background-color-N2{background-color:#676C7E;} + .d2-1659554808 .background-color-N3{background-color:#9499AB;} + .d2-1659554808 .background-color-N4{background-color:#CFD2DD;} + .d2-1659554808 .background-color-N5{background-color:#DEE1EB;} + .d2-1659554808 .background-color-N6{background-color:#EEF1F8;} + .d2-1659554808 .background-color-N7{background-color:#FFFFFF;} + .d2-1659554808 .background-color-B1{background-color:#0D32B2;} + .d2-1659554808 .background-color-B2{background-color:#0D32B2;} + .d2-1659554808 .background-color-B3{background-color:#E3E9FD;} + .d2-1659554808 .background-color-B4{background-color:#E3E9FD;} + .d2-1659554808 .background-color-B5{background-color:#EDF0FD;} + .d2-1659554808 .background-color-B6{background-color:#F7F8FE;} + .d2-1659554808 .background-color-AA2{background-color:#4A6FF3;} + .d2-1659554808 .background-color-AA4{background-color:#EDF0FD;} + .d2-1659554808 .background-color-AA5{background-color:#F7F8FE;} + .d2-1659554808 .background-color-AB4{background-color:#EDF0FD;} + .d2-1659554808 .background-color-AB5{background-color:#F7F8FE;} + .d2-1659554808 .color-N1{color:#0A0F25;} + .d2-1659554808 .color-N2{color:#676C7E;} + .d2-1659554808 .color-N3{color:#9499AB;} + .d2-1659554808 .color-N4{color:#CFD2DD;} + .d2-1659554808 .color-N5{color:#DEE1EB;} + .d2-1659554808 .color-N6{color:#EEF1F8;} + .d2-1659554808 .color-N7{color:#FFFFFF;} + .d2-1659554808 .color-B1{color:#0D32B2;} + .d2-1659554808 .color-B2{color:#0D32B2;} + .d2-1659554808 .color-B3{color:#E3E9FD;} + .d2-1659554808 .color-B4{color:#E3E9FD;} + .d2-1659554808 .color-B5{color:#EDF0FD;} + .d2-1659554808 .color-B6{color:#F7F8FE;} + .d2-1659554808 .color-AA2{color:#4A6FF3;} + .d2-1659554808 .color-AA4{color:#EDF0FD;} + .d2-1659554808 .color-AA5{color:#F7F8FE;} + .d2-1659554808 .color-AB4{color:#EDF0FD;} + .d2-1659554808 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES + \ No newline at end of file diff --git a/e2etests/testdata/stable/dagger_grid/elk/board.exp.json b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json index e8cca26bb..b94be0069 100644 --- a/e2etests/testdata/stable/dagger_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/dagger_grid/elk/board.exp.json @@ -10,7 +10,7 @@ "x": 0, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -48,10 +48,10 @@ "id": "flow2", "type": "rectangle", "pos": { - "x": 176, + "x": 168, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -89,10 +89,10 @@ "id": "flow3", "type": "rectangle", "pos": { - "x": 352, + "x": 336, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -130,10 +130,10 @@ "id": "flow4", "type": "rectangle", "pos": { - "x": 528, + "x": 504, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -171,10 +171,10 @@ "id": "flow5", "type": "rectangle", "pos": { - "x": 704, + "x": 672, "y": 0 }, - "width": 136, + "width": 128, "height": 100, "opacity": 1, "strokeDash": 0, @@ -256,7 +256,7 @@ "x": 280, "y": 140 }, - "width": 100, + "width": 120, "height": 100, "opacity": 1, "strokeDash": 0, @@ -294,10 +294,10 @@ "id": "flow8", "type": "rectangle", "pos": { - "x": 420, + "x": 440, "y": 140 }, - "width": 100, + "width": 160, "height": 100, "opacity": 1, "strokeDash": 0, @@ -335,51 +335,10 @@ "id": "flow9", "type": "rectangle", "pos": { - "x": 560, + "x": 640, "y": 140 }, - "width": 120, - "height": 100, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 10, - "borderRadius": 0, - "fill": "white", - "stroke": "cornflowerblue", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "", - "color": "N1", - "italic": false, - "bold": true, - "underline": false, - "labelWidth": 0, - "labelHeight": 0, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 1 - }, - { - "id": "flow10", - "type": "rectangle", - "pos": { - "x": 720, - "y": 140 - }, - "width": 120, + "width": 160, "height": 100, "opacity": 1, "strokeDash": 0, @@ -420,7 +379,7 @@ "x": 0, "y": 280 }, - "width": 840, + "width": 800, "height": 61, "opacity": 1, "strokeDash": 0, @@ -461,7 +420,7 @@ "x": 0, "y": 381 }, - "width": 840, + "width": 800, "height": 87, "opacity": 1, "strokeDash": 0, @@ -555,7 +514,7 @@ "x": 179, "y": 508 }, - "width": 124, + "width": 117, "height": 66, "opacity": 1, "strokeDash": 0, @@ -593,7 +552,7 @@ "id": "LINUX", "type": "rectangle", "pos": { - "x": 343, + "x": 336, "y": 508 }, "width": 139, @@ -634,10 +593,10 @@ "id": "MACOS", "type": "rectangle", "pos": { - "x": 522, + "x": 515, "y": 508 }, - "width": 139, + "width": 106, "height": 66, "opacity": 1, "strokeDash": 0, @@ -675,7 +634,7 @@ "id": "KUBERNETES", "type": "rectangle", "pos": { - "x": 701, + "x": 661, "y": 508 }, "width": 139, diff --git a/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg index 9841e85d6..cc62b273b 100644 --- a/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/dagger_grid/elk/sketch.exp.svg @@ -1,9 +1,9 @@ -DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES - + .d2-1659554808 .fill-N1{fill:#0A0F25;} + .d2-1659554808 .fill-N2{fill:#676C7E;} + .d2-1659554808 .fill-N3{fill:#9499AB;} + .d2-1659554808 .fill-N4{fill:#CFD2DD;} + .d2-1659554808 .fill-N5{fill:#DEE1EB;} + .d2-1659554808 .fill-N6{fill:#EEF1F8;} + .d2-1659554808 .fill-N7{fill:#FFFFFF;} + .d2-1659554808 .fill-B1{fill:#0D32B2;} + .d2-1659554808 .fill-B2{fill:#0D32B2;} + .d2-1659554808 .fill-B3{fill:#E3E9FD;} + .d2-1659554808 .fill-B4{fill:#E3E9FD;} + .d2-1659554808 .fill-B5{fill:#EDF0FD;} + .d2-1659554808 .fill-B6{fill:#F7F8FE;} + .d2-1659554808 .fill-AA2{fill:#4A6FF3;} + .d2-1659554808 .fill-AA4{fill:#EDF0FD;} + .d2-1659554808 .fill-AA5{fill:#F7F8FE;} + .d2-1659554808 .fill-AB4{fill:#EDF0FD;} + .d2-1659554808 .fill-AB5{fill:#F7F8FE;} + .d2-1659554808 .stroke-N1{stroke:#0A0F25;} + .d2-1659554808 .stroke-N2{stroke:#676C7E;} + .d2-1659554808 .stroke-N3{stroke:#9499AB;} + .d2-1659554808 .stroke-N4{stroke:#CFD2DD;} + .d2-1659554808 .stroke-N5{stroke:#DEE1EB;} + .d2-1659554808 .stroke-N6{stroke:#EEF1F8;} + .d2-1659554808 .stroke-N7{stroke:#FFFFFF;} + .d2-1659554808 .stroke-B1{stroke:#0D32B2;} + .d2-1659554808 .stroke-B2{stroke:#0D32B2;} + .d2-1659554808 .stroke-B3{stroke:#E3E9FD;} + .d2-1659554808 .stroke-B4{stroke:#E3E9FD;} + .d2-1659554808 .stroke-B5{stroke:#EDF0FD;} + .d2-1659554808 .stroke-B6{stroke:#F7F8FE;} + .d2-1659554808 .stroke-AA2{stroke:#4A6FF3;} + .d2-1659554808 .stroke-AA4{stroke:#EDF0FD;} + .d2-1659554808 .stroke-AA5{stroke:#F7F8FE;} + .d2-1659554808 .stroke-AB4{stroke:#EDF0FD;} + .d2-1659554808 .stroke-AB5{stroke:#F7F8FE;} + .d2-1659554808 .background-color-N1{background-color:#0A0F25;} + .d2-1659554808 .background-color-N2{background-color:#676C7E;} + .d2-1659554808 .background-color-N3{background-color:#9499AB;} + .d2-1659554808 .background-color-N4{background-color:#CFD2DD;} + .d2-1659554808 .background-color-N5{background-color:#DEE1EB;} + .d2-1659554808 .background-color-N6{background-color:#EEF1F8;} + .d2-1659554808 .background-color-N7{background-color:#FFFFFF;} + .d2-1659554808 .background-color-B1{background-color:#0D32B2;} + .d2-1659554808 .background-color-B2{background-color:#0D32B2;} + .d2-1659554808 .background-color-B3{background-color:#E3E9FD;} + .d2-1659554808 .background-color-B4{background-color:#E3E9FD;} + .d2-1659554808 .background-color-B5{background-color:#EDF0FD;} + .d2-1659554808 .background-color-B6{background-color:#F7F8FE;} + .d2-1659554808 .background-color-AA2{background-color:#4A6FF3;} + .d2-1659554808 .background-color-AA4{background-color:#EDF0FD;} + .d2-1659554808 .background-color-AA5{background-color:#F7F8FE;} + .d2-1659554808 .background-color-AB4{background-color:#EDF0FD;} + .d2-1659554808 .background-color-AB5{background-color:#F7F8FE;} + .d2-1659554808 .color-N1{color:#0A0F25;} + .d2-1659554808 .color-N2{color:#676C7E;} + .d2-1659554808 .color-N3{color:#9499AB;} + .d2-1659554808 .color-N4{color:#CFD2DD;} + .d2-1659554808 .color-N5{color:#DEE1EB;} + .d2-1659554808 .color-N6{color:#EEF1F8;} + .d2-1659554808 .color-N7{color:#FFFFFF;} + .d2-1659554808 .color-B1{color:#0D32B2;} + .d2-1659554808 .color-B2{color:#0D32B2;} + .d2-1659554808 .color-B3{color:#E3E9FD;} + .d2-1659554808 .color-B4{color:#E3E9FD;} + .d2-1659554808 .color-B5{color:#EDF0FD;} + .d2-1659554808 .color-B6{color:#F7F8FE;} + .d2-1659554808 .color-AA2{color:#4A6FF3;} + .d2-1659554808 .color-AA4{color:#EDF0FD;} + .d2-1659554808 .color-AA5{color:#F7F8FE;} + .d2-1659554808 .color-AB4{color:#EDF0FD;} + .d2-1659554808 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>DAGGER ENGINEANY DOCKER COMPATIBLE RUNTIMEANY CIWINDOWSLINUXMACOSKUBERNETES + \ No newline at end of file From d7fd7d73c3fb1b8a45b4c174c0d6c842948345e7 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 14:04:20 -0700 Subject: [PATCH 16/31] update test --- e2etests/testdata/files/teleport_grid.d2 | 9 +- .../stable/teleport_grid/dagre/board.exp.json | 131 +++++-------- .../stable/teleport_grid/dagre/sketch.exp.svg | 183 +++++++++--------- .../stable/teleport_grid/elk/board.exp.json | 115 ++++------- .../stable/teleport_grid/elk/sketch.exp.svg | 183 +++++++++--------- 5 files changed, 268 insertions(+), 353 deletions(-) diff --git a/e2etests/testdata/files/teleport_grid.d2 b/e2etests/testdata/files/teleport_grid.d2 index ca6b0acac..3a269c43b 100644 --- a/e2etests/testdata/files/teleport_grid.d2 +++ b/e2etests/testdata/files/teleport_grid.d2 @@ -31,16 +31,15 @@ via: "" { db clients: "DB Clients" } -teleport: "" { +teleport: Teleport { rows: 2 columns: 2 - t: |md - # Teleport - | inp: |md # Identity Native Proxy - | + | { + width: 300 + } Audit Log.icon: https://icons.terrastruct.com/tech%2Flaptop.svg Cert Authority.icon: https://icons.terrastruct.com/azure%2FWeb%20Service%20Color%2FApp%20Service%20Certificates.svg diff --git a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json index b9acb9863..6b5f7d1ad 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/dagre/board.exp.json @@ -92,7 +92,7 @@ "x": 1050, "y": 283 }, - "width": 584, + "width": 473, "height": 303, "opacity": 1, "strokeDash": 0, @@ -112,7 +112,7 @@ "fields": null, "methods": null, "columns": null, - "label": "", + "label": "Teleport", "fontSize": 28, "fontFamily": "DEFAULT", "language": "", @@ -120,8 +120,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0, + "labelWidth": 101, + "labelHeight": 36, "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 @@ -130,7 +130,7 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 2136, + "x": 2025, "y": 0 }, "width": 820, @@ -171,7 +171,7 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 2255, + "x": 2144, "y": 232 }, "width": 582, @@ -212,7 +212,7 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 2446, + "x": 2335, "y": 596 }, "width": 201, @@ -573,54 +573,13 @@ "level": 2 }, { - "id": "teleport.t", + "id": "teleport.inp", "type": "text", "pos": { "x": 1110, "y": 343 }, - "width": 122, - "height": 51, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "transparent", - "stroke": "N1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "# Teleport", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "markdown", - "color": "N1", - "italic": false, - "bold": false, - "underline": false, - "labelWidth": 122, - "labelHeight": 51, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "teleport.inp", - "type": "text", - "pos": { - "x": 1272, - "y": 343 - }, - "width": 302, + "width": 353, "height": 51, "opacity": 1, "strokeDash": 0, @@ -661,7 +620,7 @@ "x": 1110, "y": 434 }, - "width": 212, + "width": 140, "height": 92, "opacity": 1, "strokeDash": 0, @@ -711,10 +670,10 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 1362, + "x": 1290, "y": 434 }, - "width": 212, + "width": 173, "height": 92, "opacity": 1, "strokeDash": 0, @@ -764,7 +723,7 @@ "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 2196, + "x": 2085, "y": 60 }, "width": 110, @@ -817,7 +776,7 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 2346, + "x": 2235, "y": 60 }, "width": 128, @@ -858,7 +817,7 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 2514, + "x": 2403, "y": 60 }, "width": 72, @@ -899,7 +858,7 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 2626, + "x": 2515, "y": 60 }, "width": 119, @@ -940,7 +899,7 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 2785, + "x": 2674, "y": 60 }, "width": 111, @@ -993,7 +952,7 @@ "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 2315, + "x": 2204, "y": 292 }, "width": 108, @@ -1046,7 +1005,7 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 2463, + "x": 2352, "y": 292 }, "width": 152, @@ -1099,7 +1058,7 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 2655, + "x": 2544, "y": 292 }, "width": 122, @@ -1152,7 +1111,7 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 2315, + "x": 2204, "y": 424 }, "width": 138, @@ -1205,7 +1164,7 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 2493, + "x": 2382, "y": 424 }, "width": 108, @@ -1258,7 +1217,7 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 2641, + "x": 2530, "y": 424 }, "width": 136, @@ -1434,19 +1393,19 @@ "labelPercentage": 0, "route": [ { - "x": 1592.4246575342465, + "x": 1511.3287671232877, "y": 283 }, { - "x": 1826.4849315068493, + "x": 1721.4657534246576, "y": 141.4 }, { - "x": 1935.2, + "x": 1824.2, "y": 106 }, { - "x": 2136, + "x": 2025, "y": 106 } ], @@ -1483,19 +1442,19 @@ "labelPercentage": 0, "route": [ { - "x": 1634, - "y": 418.0985267034991 + "x": 1523, + "y": 419.70358974358976 }, { - "x": 1834.8, - "y": 406.81970534069984 + "x": 1723.8, + "y": 407.14071794871796 }, { - "x": 1959, + "x": 1848, "y": 404 }, { - "x": 2255, + "x": 2144, "y": 404 } ], @@ -1532,19 +1491,19 @@ "labelPercentage": 0, "route": [ { - "x": 1634, - "y": 501.98802946593 + "x": 1523, + "y": 495.38358974358977 }, { - "x": 1834.8, - "y": 548.397605893186 + "x": 1723.8, + "y": 547.0767179487179 }, { - "x": 1997.1, + "x": 1886.1, "y": 576.1111951588503 }, { - "x": 2445.5, + "x": 2334.5, "y": 640.5559757942511 } ], @@ -1581,19 +1540,19 @@ "labelPercentage": 0, "route": [ { - "x": 1634, - "y": 569.47605893186 + "x": 1523, + "y": 556.2671794871795 }, { - "x": 1834.8, - "y": 662.295211786372 + "x": 1723.8, + "y": 659.6534358974359 }, { - "x": 1997.1, + "x": 1886.1, "y": 680.3274583963691 }, { - "x": 2445.5, + "x": 2334.5, "y": 659.6372919818457 } ], diff --git a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg index 8490082b2..1d2b16607 100644 --- a/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/dagre/sketch.exp.svg @@ -1,23 +1,23 @@ -Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

-

Identity Native Proxy

-
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +TeleportJust-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file diff --git a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json index bb00928e2..3c2b5f426 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/teleport_grid/elk/board.exp.json @@ -92,7 +92,7 @@ "x": 660, "y": 275 }, - "width": 584, + "width": 473, "height": 303, "opacity": 1, "strokeDash": 0, @@ -112,7 +112,7 @@ "fields": null, "methods": null, "columns": null, - "label": "", + "label": "Teleport", "fontSize": 28, "fontFamily": "DEFAULT", "language": "", @@ -120,8 +120,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0, + "labelWidth": 101, + "labelHeight": 36, "labelPosition": "INSIDE_TOP_CENTER", "zIndex": 0, "level": 1 @@ -130,7 +130,7 @@ "id": "jita", "type": "rectangle", "pos": { - "x": 2026, + "x": 1915, "y": 12 }, "width": 820, @@ -171,7 +171,7 @@ "id": "infra", "type": "rectangle", "pos": { - "x": 1374, + "x": 1263, "y": 150 }, "width": 582, @@ -212,7 +212,7 @@ "id": "identity provider", "type": "rectangle", "pos": { - "x": 1374, + "x": 1263, "y": 514 }, "width": 201, @@ -573,54 +573,13 @@ "level": 2 }, { - "id": "teleport.t", + "id": "teleport.inp", "type": "text", "pos": { "x": 720, "y": 335 }, - "width": 122, - "height": 51, - "opacity": 1, - "strokeDash": 0, - "strokeWidth": 2, - "borderRadius": 0, - "fill": "transparent", - "stroke": "N1", - "shadow": false, - "3d": false, - "multiple": false, - "double-border": false, - "tooltip": "", - "link": "", - "icon": null, - "iconPosition": "", - "blend": false, - "fields": null, - "methods": null, - "columns": null, - "label": "# Teleport", - "fontSize": 16, - "fontFamily": "DEFAULT", - "language": "markdown", - "color": "N1", - "italic": false, - "bold": false, - "underline": false, - "labelWidth": 122, - "labelHeight": 51, - "labelPosition": "INSIDE_MIDDLE_CENTER", - "zIndex": 0, - "level": 2 - }, - { - "id": "teleport.inp", - "type": "text", - "pos": { - "x": 882, - "y": 335 - }, - "width": 302, + "width": 353, "height": 51, "opacity": 1, "strokeDash": 0, @@ -661,7 +620,7 @@ "x": 720, "y": 426 }, - "width": 212, + "width": 140, "height": 92, "opacity": 1, "strokeDash": 0, @@ -711,10 +670,10 @@ "id": "teleport.Cert Authority", "type": "rectangle", "pos": { - "x": 972, + "x": 900, "y": 426 }, - "width": 212, + "width": 173, "height": 92, "opacity": 1, "strokeDash": 0, @@ -764,7 +723,7 @@ "id": "jita.Slack", "type": "rectangle", "pos": { - "x": 2086, + "x": 1975, "y": 72 }, "width": 110, @@ -817,7 +776,7 @@ "id": "jita.Mattermost", "type": "rectangle", "pos": { - "x": 2236, + "x": 2125, "y": 72 }, "width": 128, @@ -858,7 +817,7 @@ "id": "jita.Jira", "type": "rectangle", "pos": { - "x": 2404, + "x": 2293, "y": 72 }, "width": 72, @@ -899,7 +858,7 @@ "id": "jita.Pagerduty", "type": "rectangle", "pos": { - "x": 2516, + "x": 2405, "y": 72 }, "width": 119, @@ -940,7 +899,7 @@ "id": "jita.Email", "type": "rectangle", "pos": { - "x": 2675, + "x": 2564, "y": 72 }, "width": 111, @@ -993,7 +952,7 @@ "id": "infra.ssh", "type": "rectangle", "pos": { - "x": 1434, + "x": 1323, "y": 210 }, "width": 108, @@ -1046,7 +1005,7 @@ "id": "infra.Kubernetes", "type": "rectangle", "pos": { - "x": 1582, + "x": 1471, "y": 210 }, "width": 152, @@ -1099,7 +1058,7 @@ "id": "infra.My SQL", "type": "rectangle", "pos": { - "x": 1774, + "x": 1663, "y": 210 }, "width": 122, @@ -1152,7 +1111,7 @@ "id": "infra.MongoDB", "type": "rectangle", "pos": { - "x": 1434, + "x": 1323, "y": 342 }, "width": 138, @@ -1205,7 +1164,7 @@ "id": "infra.PSQL", "type": "rectangle", "pos": { - "x": 1612, + "x": 1501, "y": 342 }, "width": 108, @@ -1258,7 +1217,7 @@ "id": "infra.Windows", "type": "rectangle", "pos": { - "x": 1760, + "x": 1649, "y": 342 }, "width": 136, @@ -1416,19 +1375,19 @@ "labelPercentage": 0, "route": [ { - "x": 1244, + "x": 1133, "y": 336.1333333333333 }, { - "x": 1284, + "x": 1173, "y": 336.1333333333333 }, { - "x": 1284, + "x": 1173, "y": 118 }, { - "x": 2026, + "x": 1915, "y": 118 } ], @@ -1464,11 +1423,11 @@ "labelPercentage": 0, "route": [ { - "x": 1244, + "x": 1133, "y": 396.7333333333333 }, { - "x": 1374, + "x": 1263, "y": 396.7333333333333 } ], @@ -1504,19 +1463,19 @@ "labelPercentage": 0, "route": [ { - "x": 1244, + "x": 1133, "y": 457.3333333333333 }, { - "x": 1334, + "x": 1223, "y": 457.3333333333333 }, { - "x": 1334, + "x": 1223, "y": 553.3333333333333 }, { - "x": 1374, + "x": 1263, "y": 553.3333333333333 } ], @@ -1552,19 +1511,19 @@ "labelPercentage": 0, "route": [ { - "x": 1244, + "x": 1133, "y": 517.9333333333333 }, { - "x": 1284, + "x": 1173, "y": 517.9333333333333 }, { - "x": 1284, + "x": 1173, "y": 592.6666666666666 }, { - "x": 1374, + "x": 1263, "y": 592.6666666666666 } ], diff --git a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg index 0f29b7d25..f5b39beb8 100644 --- a/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/teleport_grid/elk/sketch.exp.svg @@ -1,23 +1,23 @@ -Just-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Teleport

-

Identity Native Proxy

-
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged - - +TeleportJust-in-time Access viaInfrastructureIndentity ProviderEngineersMachinesHTTPS://> kubectl> tsh> apiDB Clients

Identity Native Proxy

+
Audit LogCert AuthoritySlackMattermostJiraPagerdutyEmailsshKubernetesMy SQLMongoDBPSQLWindows all connections audited and logged + +
\ No newline at end of file From bce774fd4a9944954b67f77d3991b940d31bf5bf Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 17:44:05 -0700 Subject: [PATCH 17/31] validate edges --- d2compiler/compile.go | 14 +++++++++++++ d2compiler/compile_test.go | 15 ++++++++++++++ d2graph/d2graph.go | 4 ++++ d2graph/grid.go | 10 ++++++++++ .../d2compiler/TestCompile/grid_edge.exp.json | 20 +++++++++++++++++++ 5 files changed, 63 insertions(+) create mode 100644 testdata/d2compiler/TestCompile/grid_edge.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 66940ce56..0236a9ce2 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -73,6 +73,7 @@ func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph { c.validateKeys(g.Root, ir) } c.validateNear(g) + c.validateEdges(g) c.compileBoardsField(g, ir, "layers") c.compileBoardsField(g, ir, "scenarios") @@ -787,6 +788,19 @@ func (c *compiler) validateNear(g *d2graph.Graph) { } } +func (c *compiler) validateEdges(g *d2graph.Graph) { + for _, edge := range g.Edges { + if grid := edge.Src.ClosestGrid(); grid != nil { + c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid %#v", d2format.Format(edge.GetAstEdge()), grid.AbsID()) + continue + } + if grid := edge.Dst.ClosestGrid(); grid != nil { + c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid %#v", d2format.Format(edge.GetAstEdge()), grid.AbsID()) + continue + } + } +} + func (c *compiler) validateBoardLinks(g *d2graph.Graph) { for _, obj := range g.Objects { if obj.Attributes.Link == nil { diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 2d6e63a95..4afc52fbf 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2288,6 +2288,21 @@ obj { `, expErr: `d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a positive integer: "-200"`, }, + { + name: "grid_edge", + text: `hey: { + rows: 1 + a -> b +} + c -> hey.b + hey.a -> c + + hey -> c: ok +`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge "a -> b" cannot enter grid "hey" +d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge "c -> hey.b" cannot enter grid "hey" +d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge "hey.a -> c" cannot enter grid "hey"`, + }, } for _, tc := range testCases { diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 42f42977a..d9ae9a89d 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -1013,6 +1013,10 @@ type EdgeReference struct { ScopeObj *Object `json:"-"` } +func (e *Edge) GetAstEdge() *d2ast.Edge { + return e.References[0].Edge +} + func (e *Edge) GetStroke(dashGapSize interface{}) string { if dashGapSize != 0.0 { return color.B2 diff --git a/d2graph/grid.go b/d2graph/grid.go index 1ff029bba..0315fe60b 100644 --- a/d2graph/grid.go +++ b/d2graph/grid.go @@ -4,3 +4,13 @@ func (obj *Object) IsGrid() bool { return obj != nil && obj.Attributes != nil && (obj.Attributes.Rows != nil || obj.Attributes.Columns != nil) } + +func (obj *Object) ClosestGrid() *Object { + if obj.Parent == nil { + return nil + } + if obj.Parent.IsGrid() { + return obj.Parent + } + return obj.Parent.ClosestGrid() +} diff --git a/testdata/d2compiler/TestCompile/grid_edge.exp.json b/testdata/d2compiler/TestCompile/grid_edge.exp.json new file mode 100644 index 000000000..1d6c84181 --- /dev/null +++ b/testdata/d2compiler/TestCompile/grid_edge.exp.json @@ -0,0 +1,20 @@ +{ + "graph": null, + "err": { + "ioerr": null, + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,2:1:17-2:7:23", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge \"a -> b\" cannot enter grid \"hey\"" + }, + { + "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,4:1:27-4:11:37", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge \"c -> hey.b\" cannot enter grid \"hey\"" + }, + { + "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,5:1:39-5:11:49", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge \"hey.a -> c\" cannot enter grid \"hey\"" + } + ] + } +} From ac0845da1c35e50c639d6248f9fa65feddeb6bfa Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 19:07:49 -0700 Subject: [PATCH 18/31] center container if growing to fit label --- d2layouts/d2grid/layout.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index c16529fe0..69050c15d 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -69,7 +69,28 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g } obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = nil - obj.Box = geo.NewBox(nil, grid.width+2*CONTAINER_PADDING, grid.height+2*CONTAINER_PADDING) + + var dx, dy float64 + width := grid.width + 2*CONTAINER_PADDING + labelWidth := float64(obj.LabelDimensions.Width) + 2*label.PADDING + if labelWidth > width { + dx = (labelWidth - width) / 2 + width = labelWidth + } + height := grid.height + 2*CONTAINER_PADDING + labelHeight := float64(obj.LabelDimensions.Height) + 2*label.PADDING + if labelHeight > CONTAINER_PADDING { + // if the label doesn't fit within the padding, we need to add more + grow := labelHeight - CONTAINER_PADDING + dy = grow / 2 + height += grow + } + // we need to center children if we have to expand to fit the container label + if dx != 0 || dy != 0 { + grid.shift(dx, dy) + } + obj.Box = geo.NewBox(nil, width, height) + obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) grids[obj.AbsID()] = grid From 108faceb998eaa41e3f7322a0a33a762b6deb073 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 20:02:22 -0700 Subject: [PATCH 19/31] layout evenly with rows and columns --- d2layouts/d2grid/grid.go | 6 +- d2layouts/d2grid/layout.go | 122 +++++++++++++++++++++++++++++++++---- 2 files changed, 112 insertions(+), 16 deletions(-) diff --git a/d2layouts/d2grid/grid.go b/d2layouts/d2grid/grid.go index 22cc23afd..f5d6e7b65 100644 --- a/d2layouts/d2grid/grid.go +++ b/d2layouts/d2grid/grid.go @@ -14,10 +14,8 @@ type grid struct { rowDominant bool - cellWidth float64 - cellHeight float64 - width float64 - height float64 + width float64 + height float64 } func newGrid(root *d2graph.Object) *grid { diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 69050c15d..3bdc0a4be 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -115,6 +115,116 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { grid := newGrid(obj) + + if grid.rows != 0 && grid.columns != 0 { + grid.layoutEvenly(g, obj) + } else { + grid.layoutDynamic(g, obj) + } + + // position labels and icons + for _, n := range grid.nodes { + if n.Attributes.Icon != nil { + n.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) + n.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } else { + n.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } + } + + return grid, nil +} + +func (grid *grid) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { + // layout nodes in a grid with these 2 properties: + // all nodes in the same row should have the same height + // all nodes in the same column should have the same width + + getNode := func(rowIndex, columnIndex int) *d2graph.Object { + var index int + if grid.rowDominant { + index = rowIndex*grid.columns + columnIndex + } else { + index = columnIndex*grid.rows + rowIndex + } + if index < len(grid.nodes) { + return grid.nodes[index] + } + return nil + } + + rowHeights := make([]float64, 0, grid.rows) + colWidths := make([]float64, 0, grid.columns) + for i := 0; i < grid.rows; i++ { + rowHeight := 0. + for j := 0; j < grid.columns; j++ { + n := getNode(i, j) + if n == nil { + break + } + rowHeight = math.Max(rowHeight, n.Height) + } + rowHeights = append(rowHeights, rowHeight) + } + for j := 0; j < grid.columns; j++ { + columnWidth := 0. + for i := 0; i < grid.rows; i++ { + n := getNode(i, j) + if n == nil { + break + } + columnWidth = math.Max(columnWidth, n.Width) + } + colWidths = append(colWidths, columnWidth) + } + + cursor := geo.NewPoint(0, 0) + if grid.rowDominant { + for i := 0; i < grid.rows; i++ { + for j := 0; j < grid.columns; j++ { + n := getNode(i, j) + if n == nil { + break + } + n.Width = colWidths[j] + n.Height = rowHeights[i] + n.TopLeft = cursor.Copy() + cursor.X += n.Width + HORIZONTAL_PAD + } + cursor.X = 0 + cursor.Y += rowHeights[i] + VERTICAL_PAD + } + } else { + for j := 0; j < grid.columns; j++ { + for i := 0; i < grid.rows; i++ { + n := getNode(i, j) + if n == nil { + break + } + n.Width = colWidths[j] + n.Height = rowHeights[i] + n.TopLeft = cursor.Copy() + cursor.Y += n.Height + VERTICAL_PAD + } + cursor.X += colWidths[j] + HORIZONTAL_PAD + cursor.Y = 0 + } + } + + var totalWidth, totalHeight float64 + for _, w := range colWidths { + totalWidth += w + HORIZONTAL_PAD + } + for _, h := range rowHeights { + totalHeight += h + VERTICAL_PAD + } + totalWidth -= HORIZONTAL_PAD + totalHeight -= VERTICAL_PAD + grid.width = totalWidth + grid.height = totalHeight +} + +func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { // assume we have the following nodes to layout: // . ┌A──────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐ // . └───────────────┘ │ │ │ │ │ │ │ │ @@ -401,18 +511,6 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { } grid.width = maxX grid.height = maxY - - // position labels and icons - for _, n := range grid.nodes { - if n.Attributes.Icon != nil { - n.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) - n.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) - } else { - n.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) - } - } - - return grid, nil } // cleanup restores the graph after the core layout engine finishes From 69ceb5be1a88b92bb27d5ad3d1c66bd81d2487e4 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 18:56:40 -0700 Subject: [PATCH 20/31] add grid_tests test --- e2etests/stable_test.go | 1 + e2etests/testdata/files/grid_tests.d2 | 119 + e2etests/testdata/files/teleport_grid.d2 | 1 - .../stable/grid_tests/dagre/board.exp.json | 3328 +++++++++++++++++ .../stable/grid_tests/dagre/sketch.exp.svg | 102 + .../stable/grid_tests/elk/board.exp.json | 3328 +++++++++++++++++ .../stable/grid_tests/elk/sketch.exp.svg | 102 + 7 files changed, 6980 insertions(+), 1 deletion(-) create mode 100644 e2etests/testdata/files/grid_tests.d2 create mode 100644 e2etests/testdata/stable/grid_tests/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/grid_tests/elk/board.exp.json create mode 100644 e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index 4499dafca..325a79759 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -2467,6 +2467,7 @@ scenarios: { loadFromFile(t, "arrowhead_scaling"), loadFromFile(t, "teleport_grid"), loadFromFile(t, "dagger_grid"), + loadFromFile(t, "grid_tests"), } runa(t, tcs) diff --git a/e2etests/testdata/files/grid_tests.d2 b/e2etests/testdata/files/grid_tests.d2 new file mode 100644 index 000000000..d4b02f841 --- /dev/null +++ b/e2etests/testdata/files/grid_tests.d2 @@ -0,0 +1,119 @@ +rows 1: { + rows: 1 + a + b + c + d + e + f + g +} + +columns 1: { + columns: 1 + a + b + c + d + e + f + g +} + +rows 2: { + rows: 2 + a + b + c + d + e + f + g +} + +columns 2: { + columns: 2 + a + b + c + d + e + f + g +} + +rows 2 columns 2: { + rows: 2 + columns: 2 + + a + b + c + d + e + f + g +} + +columns 2 rows 2: { + columns: 2 + rows: 2 + + a + b + c + d + e + f + g +} + +rows 3 columns 3: { + rows: 3 + columns: 3 + + a + b + c + d + e + f + g +} + +columns 3 rows 3: { + columns: 3 + rows: 3 + + a + b + c + d + e + f + g +} + +rows 3: { + rows: 3 + + a + b + c + d + e + f + g +} + +columns 3: { + columns: 3 + + a + b + c + d + e + f + g +} diff --git a/e2etests/testdata/files/teleport_grid.d2 b/e2etests/testdata/files/teleport_grid.d2 index 3a269c43b..baec9fe60 100644 --- a/e2etests/testdata/files/teleport_grid.d2 +++ b/e2etests/testdata/files/teleport_grid.d2 @@ -33,7 +33,6 @@ via: "" { teleport: Teleport { rows: 2 - columns: 2 inp: |md # Identity Native Proxy diff --git a/e2etests/testdata/stable/grid_tests/dagre/board.exp.json b/e2etests/testdata/stable/grid_tests/dagre/board.exp.json new file mode 100644 index 000000000..431f1dd28 --- /dev/null +++ b/e2etests/testdata/stable/grid_tests/dagre/board.exp.json @@ -0,0 +1,3328 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "rows 1", + "type": "rectangle", + "pos": { + "x": 0, + "y": 318 + }, + "width": 731, + "height": 186, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 1", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 74, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 1.a", + "type": "rectangle", + "pos": { + "x": 60, + "y": 378 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.b", + "type": "rectangle", + "pos": { + "x": 153, + "y": 378 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.c", + "type": "rectangle", + "pos": { + "x": 246, + "y": 378 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.d", + "type": "rectangle", + "pos": { + "x": 339, + "y": 378 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.e", + "type": "rectangle", + "pos": { + "x": 433, + "y": 378 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.f", + "type": "rectangle", + "pos": { + "x": 526, + "y": 378 + }, + "width": 51, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.g", + "type": "rectangle", + "pos": { + "x": 617, + "y": 378 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1", + "type": "rectangle", + "pos": { + "x": 791, + "y": 0 + }, + "width": 174, + "height": 822, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 1", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 119, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 1.a", + "type": "rectangle", + "pos": { + "x": 851, + "y": 60 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.b", + "type": "rectangle", + "pos": { + "x": 851, + "y": 166 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.c", + "type": "rectangle", + "pos": { + "x": 851, + "y": 272 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.d", + "type": "rectangle", + "pos": { + "x": 851, + "y": 378 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.e", + "type": "rectangle", + "pos": { + "x": 851, + "y": 484 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.f", + "type": "rectangle", + "pos": { + "x": 851, + "y": 590 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.g", + "type": "rectangle", + "pos": { + "x": 851, + "y": 696 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2", + "type": "rectangle", + "pos": { + "x": 1025, + "y": 265 + }, + "width": 452, + "height": 292, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 74, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 2.a", + "type": "rectangle", + "pos": { + "x": 1085, + "y": 325 + }, + "width": 84, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.b", + "type": "rectangle", + "pos": { + "x": 1209, + "y": 325 + }, + "width": 84, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.c", + "type": "rectangle", + "pos": { + "x": 1333, + "y": 325 + }, + "width": 84, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.d", + "type": "rectangle", + "pos": { + "x": 1085, + "y": 431 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.e", + "type": "rectangle", + "pos": { + "x": 1179, + "y": 431 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.f", + "type": "rectangle", + "pos": { + "x": 1272, + "y": 431 + }, + "width": 51, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.g", + "type": "rectangle", + "pos": { + "x": 1363, + "y": 431 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2", + "type": "rectangle", + "pos": { + "x": 1537, + "y": 159 + }, + "width": 268, + "height": 504, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 119, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 2.a", + "type": "rectangle", + "pos": { + "x": 1597, + "y": 219 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.b", + "type": "rectangle", + "pos": { + "x": 1597, + "y": 325 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.c", + "type": "rectangle", + "pos": { + "x": 1597, + "y": 431 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.d", + "type": "rectangle", + "pos": { + "x": 1597, + "y": 537 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.e", + "type": "rectangle", + "pos": { + "x": 1691, + "y": 219 + }, + "width": 54, + "height": 101, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.f", + "type": "rectangle", + "pos": { + "x": 1691, + "y": 360 + }, + "width": 54, + "height": 101, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.g", + "type": "rectangle", + "pos": { + "x": 1691, + "y": 501 + }, + "width": 54, + "height": 101, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2", + "type": "rectangle", + "pos": { + "x": 1865, + "y": 159 + }, + "width": 268, + "height": 504, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 2 columns 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 200, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 2 columns 2.a", + "type": "rectangle", + "pos": { + "x": 1925, + "y": 219 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.b", + "type": "rectangle", + "pos": { + "x": 2019, + "y": 219 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.c", + "type": "rectangle", + "pos": { + "x": 1925, + "y": 325 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.d", + "type": "rectangle", + "pos": { + "x": 2019, + "y": 325 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.e", + "type": "rectangle", + "pos": { + "x": 1925, + "y": 431 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.f", + "type": "rectangle", + "pos": { + "x": 2019, + "y": 431 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.g", + "type": "rectangle", + "pos": { + "x": 1925, + "y": 537 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2", + "type": "rectangle", + "pos": { + "x": 2193, + "y": 265 + }, + "width": 454, + "height": 292, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 2 rows 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 201, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 2 rows 2.a", + "type": "rectangle", + "pos": { + "x": 2253, + "y": 325 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.b", + "type": "rectangle", + "pos": { + "x": 2253, + "y": 431 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.c", + "type": "rectangle", + "pos": { + "x": 2346, + "y": 325 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.d", + "type": "rectangle", + "pos": { + "x": 2346, + "y": 431 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.e", + "type": "rectangle", + "pos": { + "x": 2440, + "y": 325 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.f", + "type": "rectangle", + "pos": { + "x": 2440, + "y": 431 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.g", + "type": "rectangle", + "pos": { + "x": 2533, + "y": 325 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3", + "type": "rectangle", + "pos": { + "x": 2707, + "y": 212 + }, + "width": 360, + "height": 398, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 3 columns 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 200, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 3 columns 3.a", + "type": "rectangle", + "pos": { + "x": 2767, + "y": 272 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.b", + "type": "rectangle", + "pos": { + "x": 2861, + "y": 272 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.c", + "type": "rectangle", + "pos": { + "x": 2954, + "y": 272 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.d", + "type": "rectangle", + "pos": { + "x": 2767, + "y": 378 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.e", + "type": "rectangle", + "pos": { + "x": 2861, + "y": 378 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.f", + "type": "rectangle", + "pos": { + "x": 2954, + "y": 378 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.g", + "type": "rectangle", + "pos": { + "x": 2767, + "y": 484 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3", + "type": "rectangle", + "pos": { + "x": 3127, + "y": 212 + }, + "width": 361, + "height": 398, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 3 rows 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 201, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 3 rows 3.a", + "type": "rectangle", + "pos": { + "x": 3187, + "y": 272 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.b", + "type": "rectangle", + "pos": { + "x": 3187, + "y": 378 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.c", + "type": "rectangle", + "pos": { + "x": 3187, + "y": 484 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.d", + "type": "rectangle", + "pos": { + "x": 3280, + "y": 272 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.e", + "type": "rectangle", + "pos": { + "x": 3280, + "y": 378 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.f", + "type": "rectangle", + "pos": { + "x": 3280, + "y": 484 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.g", + "type": "rectangle", + "pos": { + "x": 3374, + "y": 272 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3", + "type": "rectangle", + "pos": { + "x": 3548, + "y": 159 + }, + "width": 267, + "height": 504, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 74, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 3.a", + "type": "rectangle", + "pos": { + "x": 3608, + "y": 219 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.b", + "type": "rectangle", + "pos": { + "x": 3701, + "y": 219 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.c", + "type": "rectangle", + "pos": { + "x": 3608, + "y": 325 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.d", + "type": "rectangle", + "pos": { + "x": 3701, + "y": 325 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.e", + "type": "rectangle", + "pos": { + "x": 3608, + "y": 431 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.f", + "type": "rectangle", + "pos": { + "x": 3701, + "y": 431 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.g", + "type": "rectangle", + "pos": { + "x": 3608, + "y": 537 + }, + "width": 147, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3", + "type": "rectangle", + "pos": { + "x": 3875, + "y": 265 + }, + "width": 454, + "height": 292, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 119, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 3.a", + "type": "rectangle", + "pos": { + "x": 3935, + "y": 325 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.b", + "type": "rectangle", + "pos": { + "x": 3935, + "y": 431 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.c", + "type": "rectangle", + "pos": { + "x": 4028, + "y": 325 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.d", + "type": "rectangle", + "pos": { + "x": 4028, + "y": 431 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.e", + "type": "rectangle", + "pos": { + "x": 4122, + "y": 325 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.f", + "type": "rectangle", + "pos": { + "x": 4122, + "y": 431 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.g", + "type": "rectangle", + "pos": { + "x": 4215, + "y": 325 + }, + "width": 54, + "height": 172, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg b/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg new file mode 100644 index 000000000..9e87e99d6 --- /dev/null +++ b/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg @@ -0,0 +1,102 @@ +rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/grid_tests/elk/board.exp.json b/e2etests/testdata/stable/grid_tests/elk/board.exp.json new file mode 100644 index 000000000..e1fd68bee --- /dev/null +++ b/e2etests/testdata/stable/grid_tests/elk/board.exp.json @@ -0,0 +1,3328 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "rows 1", + "type": "rectangle", + "pos": { + "x": 12, + "y": 330 + }, + "width": 731, + "height": 186, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 1", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 74, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 1.a", + "type": "rectangle", + "pos": { + "x": 72, + "y": 390 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.b", + "type": "rectangle", + "pos": { + "x": 165, + "y": 390 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.c", + "type": "rectangle", + "pos": { + "x": 258, + "y": 390 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.d", + "type": "rectangle", + "pos": { + "x": 351, + "y": 390 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.e", + "type": "rectangle", + "pos": { + "x": 445, + "y": 390 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.f", + "type": "rectangle", + "pos": { + "x": 538, + "y": 390 + }, + "width": 51, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 1.g", + "type": "rectangle", + "pos": { + "x": 629, + "y": 390 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1", + "type": "rectangle", + "pos": { + "x": 763, + "y": 12 + }, + "width": 174, + "height": 822, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 1", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 119, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 1.a", + "type": "rectangle", + "pos": { + "x": 823, + "y": 72 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.b", + "type": "rectangle", + "pos": { + "x": 823, + "y": 178 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.c", + "type": "rectangle", + "pos": { + "x": 823, + "y": 284 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.d", + "type": "rectangle", + "pos": { + "x": 823, + "y": 390 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.e", + "type": "rectangle", + "pos": { + "x": 823, + "y": 496 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.f", + "type": "rectangle", + "pos": { + "x": 823, + "y": 602 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 1.g", + "type": "rectangle", + "pos": { + "x": 823, + "y": 708 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2", + "type": "rectangle", + "pos": { + "x": 957, + "y": 277 + }, + "width": 452, + "height": 292, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 74, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 2.a", + "type": "rectangle", + "pos": { + "x": 1017, + "y": 337 + }, + "width": 84, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.b", + "type": "rectangle", + "pos": { + "x": 1141, + "y": 337 + }, + "width": 84, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.c", + "type": "rectangle", + "pos": { + "x": 1265, + "y": 337 + }, + "width": 84, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.d", + "type": "rectangle", + "pos": { + "x": 1017, + "y": 443 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.e", + "type": "rectangle", + "pos": { + "x": 1111, + "y": 443 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.f", + "type": "rectangle", + "pos": { + "x": 1204, + "y": 443 + }, + "width": 51, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2.g", + "type": "rectangle", + "pos": { + "x": 1295, + "y": 443 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2", + "type": "rectangle", + "pos": { + "x": 1429, + "y": 171 + }, + "width": 268, + "height": 504, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 119, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 2.a", + "type": "rectangle", + "pos": { + "x": 1489, + "y": 231 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.b", + "type": "rectangle", + "pos": { + "x": 1489, + "y": 337 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.c", + "type": "rectangle", + "pos": { + "x": 1489, + "y": 443 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.d", + "type": "rectangle", + "pos": { + "x": 1489, + "y": 549 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.e", + "type": "rectangle", + "pos": { + "x": 1583, + "y": 231 + }, + "width": 54, + "height": 101, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.f", + "type": "rectangle", + "pos": { + "x": 1583, + "y": 372 + }, + "width": 54, + "height": 101, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2.g", + "type": "rectangle", + "pos": { + "x": 1583, + "y": 513 + }, + "width": 54, + "height": 101, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2", + "type": "rectangle", + "pos": { + "x": 1717, + "y": 171 + }, + "width": 268, + "height": 504, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 2 columns 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 200, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 2 columns 2.a", + "type": "rectangle", + "pos": { + "x": 1777, + "y": 231 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.b", + "type": "rectangle", + "pos": { + "x": 1871, + "y": 231 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.c", + "type": "rectangle", + "pos": { + "x": 1777, + "y": 337 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.d", + "type": "rectangle", + "pos": { + "x": 1871, + "y": 337 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.e", + "type": "rectangle", + "pos": { + "x": 1777, + "y": 443 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.f", + "type": "rectangle", + "pos": { + "x": 1871, + "y": 443 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 2 columns 2.g", + "type": "rectangle", + "pos": { + "x": 1777, + "y": 549 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2", + "type": "rectangle", + "pos": { + "x": 2005, + "y": 277 + }, + "width": 454, + "height": 292, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 2 rows 2", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 201, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 2 rows 2.a", + "type": "rectangle", + "pos": { + "x": 2065, + "y": 337 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.b", + "type": "rectangle", + "pos": { + "x": 2065, + "y": 443 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.c", + "type": "rectangle", + "pos": { + "x": 2158, + "y": 337 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.d", + "type": "rectangle", + "pos": { + "x": 2158, + "y": 443 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.e", + "type": "rectangle", + "pos": { + "x": 2252, + "y": 337 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.f", + "type": "rectangle", + "pos": { + "x": 2252, + "y": 443 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 2 rows 2.g", + "type": "rectangle", + "pos": { + "x": 2345, + "y": 337 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3", + "type": "rectangle", + "pos": { + "x": 2479, + "y": 224 + }, + "width": 360, + "height": 398, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 3 columns 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 200, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 3 columns 3.a", + "type": "rectangle", + "pos": { + "x": 2539, + "y": 284 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.b", + "type": "rectangle", + "pos": { + "x": 2633, + "y": 284 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.c", + "type": "rectangle", + "pos": { + "x": 2726, + "y": 284 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.d", + "type": "rectangle", + "pos": { + "x": 2539, + "y": 390 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.e", + "type": "rectangle", + "pos": { + "x": 2633, + "y": 390 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.f", + "type": "rectangle", + "pos": { + "x": 2726, + "y": 390 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3 columns 3.g", + "type": "rectangle", + "pos": { + "x": 2539, + "y": 496 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3", + "type": "rectangle", + "pos": { + "x": 2859, + "y": 224 + }, + "width": 361, + "height": 398, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 3 rows 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 201, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 3 rows 3.a", + "type": "rectangle", + "pos": { + "x": 2919, + "y": 284 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.b", + "type": "rectangle", + "pos": { + "x": 2919, + "y": 390 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.c", + "type": "rectangle", + "pos": { + "x": 2919, + "y": 496 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.d", + "type": "rectangle", + "pos": { + "x": 3012, + "y": 284 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.e", + "type": "rectangle", + "pos": { + "x": 3012, + "y": 390 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.f", + "type": "rectangle", + "pos": { + "x": 3012, + "y": 496 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3 rows 3.g", + "type": "rectangle", + "pos": { + "x": 3106, + "y": 284 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3", + "type": "rectangle", + "pos": { + "x": 3240, + "y": 171 + }, + "width": 267, + "height": 504, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "rows 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 74, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "rows 3.a", + "type": "rectangle", + "pos": { + "x": 3300, + "y": 231 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.b", + "type": "rectangle", + "pos": { + "x": 3393, + "y": 231 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.c", + "type": "rectangle", + "pos": { + "x": 3300, + "y": 337 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.d", + "type": "rectangle", + "pos": { + "x": 3393, + "y": 337 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.e", + "type": "rectangle", + "pos": { + "x": 3300, + "y": 443 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.f", + "type": "rectangle", + "pos": { + "x": 3393, + "y": 443 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "rows 3.g", + "type": "rectangle", + "pos": { + "x": 3300, + "y": 549 + }, + "width": 147, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3", + "type": "rectangle", + "pos": { + "x": 3527, + "y": 277 + }, + "width": 454, + "height": 292, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "columns 3", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 119, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "columns 3.a", + "type": "rectangle", + "pos": { + "x": 3587, + "y": 337 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.b", + "type": "rectangle", + "pos": { + "x": 3587, + "y": 443 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.c", + "type": "rectangle", + "pos": { + "x": 3680, + "y": 337 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.d", + "type": "rectangle", + "pos": { + "x": 3680, + "y": 443 + }, + "width": 54, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.e", + "type": "rectangle", + "pos": { + "x": 3774, + "y": 337 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.f", + "type": "rectangle", + "pos": { + "x": 3774, + "y": 443 + }, + "width": 53, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 6, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "columns 3.g", + "type": "rectangle", + "pos": { + "x": 3867, + "y": 337 + }, + "width": 54, + "height": 172, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + } + ], + "connections": [], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg b/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg new file mode 100644 index 000000000..0004db37f --- /dev/null +++ b/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg @@ -0,0 +1,102 @@ +rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg + + + \ No newline at end of file From 18e72880e0c699d33c2f773602fd6fe575d0e2a2 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 20:19:42 -0700 Subject: [PATCH 21/31] add executive_grid test --- e2etests/stable_test.go | 1 + e2etests/testdata/files/executive_grid.d2 | 15 + .../executive_grid/dagre/board.exp.json | 458 ++++++++++++++++++ .../executive_grid/dagre/sketch.exp.svg | 95 ++++ .../stable/executive_grid/elk/board.exp.json | 458 ++++++++++++++++++ .../stable/executive_grid/elk/sketch.exp.svg | 95 ++++ 6 files changed, 1122 insertions(+) create mode 100644 e2etests/testdata/files/executive_grid.d2 create mode 100644 e2etests/testdata/stable/executive_grid/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/executive_grid/elk/board.exp.json create mode 100644 e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index 325a79759..99aff1872 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -2468,6 +2468,7 @@ scenarios: { loadFromFile(t, "teleport_grid"), loadFromFile(t, "dagger_grid"), loadFromFile(t, "grid_tests"), + loadFromFile(t, "executive_grid"), } runa(t, tcs) diff --git a/e2etests/testdata/files/executive_grid.d2 b/e2etests/testdata/files/executive_grid.d2 new file mode 100644 index 000000000..580d00622 --- /dev/null +++ b/e2etests/testdata/files/executive_grid.d2 @@ -0,0 +1,15 @@ +rows: 3 + +Executive Services.width: 1000 + +I/O\nManager.width: 100 +Security\nReference\nMonitor.width: 100 +IPC\nManager.width: 100 +Virtual\nMemory\nManager\n(VMM).width: 100 +Process\nManager.width: 100 +PnP\nManager.width: 100 +Power\nManager.width: 100 +# TODO recursive grids +Window\nManager\n\nGDI.width: 100 + +Object Manager.width: 1000 diff --git a/e2etests/testdata/stable/executive_grid/dagre/board.exp.json b/e2etests/testdata/stable/executive_grid/dagre/board.exp.json new file mode 100644 index 000000000..b9f09e5b5 --- /dev/null +++ b/e2etests/testdata/stable/executive_grid/dagre/board.exp.json @@ -0,0 +1,458 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "Executive Services", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 1080, + "height": 61, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Executive Services", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 131, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"I/O\\nManager\"", + "type": "rectangle", + "pos": { + "x": 0, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "I/O\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Security\\nReference\\nMonitor\"", + "type": "rectangle", + "pos": { + "x": 140, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Security\nReference\nMonitor", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 72, + "labelHeight": 53, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"IPC\\nManager\"", + "type": "rectangle", + "pos": { + "x": 280, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "IPC\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Virtual\\nMemory\\nManager\\n(VMM)\"", + "type": "rectangle", + "pos": { + "x": 420, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Virtual\nMemory\nManager\n(VMM)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 69, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Process\\nManager\"", + "type": "rectangle", + "pos": { + "x": 560, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Process\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"PnP\\nManager\"", + "type": "rectangle", + "pos": { + "x": 700, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "PnP\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Power\\nManager\"", + "type": "rectangle", + "pos": { + "x": 840, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Power\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Window\\nManager\\n\\nGDI\"", + "type": "rectangle", + "pos": { + "x": 980, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Window\nManager\n\nGDI", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 63, + "labelHeight": 69, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "Object Manager", + "type": "rectangle", + "pos": { + "x": 0, + "y": 250 + }, + "width": 1080, + "height": 61, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Object Manager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 112, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg new file mode 100644 index 000000000..7ac1c0a8a --- /dev/null +++ b/e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg @@ -0,0 +1,95 @@ +Executive ServicesI/OManagerSecurityReferenceMonitorIPCManagerVirtualMemoryManager(VMM)ProcessManagerPnPManagerPowerManagerWindowManager GDIObject Manager + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/executive_grid/elk/board.exp.json b/e2etests/testdata/stable/executive_grid/elk/board.exp.json new file mode 100644 index 000000000..b9f09e5b5 --- /dev/null +++ b/e2etests/testdata/stable/executive_grid/elk/board.exp.json @@ -0,0 +1,458 @@ +{ + "name": "", + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "Executive Services", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 1080, + "height": 61, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Executive Services", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 131, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"I/O\\nManager\"", + "type": "rectangle", + "pos": { + "x": 0, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "I/O\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Security\\nReference\\nMonitor\"", + "type": "rectangle", + "pos": { + "x": 140, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Security\nReference\nMonitor", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 72, + "labelHeight": 53, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"IPC\\nManager\"", + "type": "rectangle", + "pos": { + "x": 280, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "IPC\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Virtual\\nMemory\\nManager\\n(VMM)\"", + "type": "rectangle", + "pos": { + "x": 420, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Virtual\nMemory\nManager\n(VMM)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 69, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Process\\nManager\"", + "type": "rectangle", + "pos": { + "x": 560, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Process\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"PnP\\nManager\"", + "type": "rectangle", + "pos": { + "x": 700, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "PnP\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Power\\nManager\"", + "type": "rectangle", + "pos": { + "x": 840, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Power\nManager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 62, + "labelHeight": 37, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"Window\\nManager\\n\\nGDI\"", + "type": "rectangle", + "pos": { + "x": 980, + "y": 101 + }, + "width": 100, + "height": 109, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Window\nManager\n\nGDI", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 63, + "labelHeight": 69, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "Object Manager", + "type": "rectangle", + "pos": { + "x": 0, + "y": 250 + }, + "width": 1080, + "height": 61, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "Object Manager", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 112, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg new file mode 100644 index 000000000..7ac1c0a8a --- /dev/null +++ b/e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg @@ -0,0 +1,95 @@ +Executive ServicesI/OManagerSecurityReferenceMonitorIPCManagerVirtualMemoryManager(VMM)ProcessManagerPnPManagerPowerManagerWindowManager GDIObject Manager + + + \ No newline at end of file From 0dc6a808e3fb876d7a288e13af331f202033020b Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 20:23:18 -0700 Subject: [PATCH 22/31] update test --- e2etests/testdata/files/executive_grid.d2 | 1 + .../executive_grid/dagre/board.exp.json | 18 +- .../executive_grid/dagre/sketch.exp.svg | 154 +++++++++--------- .../stable/executive_grid/elk/board.exp.json | 18 +- .../stable/executive_grid/elk/sketch.exp.svg | 154 +++++++++--------- 5 files changed, 173 insertions(+), 172 deletions(-) diff --git a/e2etests/testdata/files/executive_grid.d2 b/e2etests/testdata/files/executive_grid.d2 index 580d00622..4a3a5c3ab 100644 --- a/e2etests/testdata/files/executive_grid.d2 +++ b/e2etests/testdata/files/executive_grid.d2 @@ -3,6 +3,7 @@ rows: 3 Executive Services.width: 1000 I/O\nManager.width: 100 +I/O\nManager.height: 200 Security\nReference\nMonitor.width: 100 IPC\nManager.width: 100 Virtual\nMemory\nManager\n(VMM).width: 100 diff --git a/e2etests/testdata/stable/executive_grid/dagre/board.exp.json b/e2etests/testdata/stable/executive_grid/dagre/board.exp.json index b9f09e5b5..6ec7a989f 100644 --- a/e2etests/testdata/stable/executive_grid/dagre/board.exp.json +++ b/e2etests/testdata/stable/executive_grid/dagre/board.exp.json @@ -52,7 +52,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -93,7 +93,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -134,7 +134,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -175,7 +175,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -216,7 +216,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -257,7 +257,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -298,7 +298,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -339,7 +339,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -377,7 +377,7 @@ "type": "rectangle", "pos": { "x": 0, - "y": 250 + "y": 341 }, "width": 1080, "height": 61, diff --git a/e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg b/e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg index 7ac1c0a8a..8b27b5168 100644 --- a/e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/executive_grid/dagre/sketch.exp.svg @@ -1,9 +1,9 @@ -Executive ServicesI/OManagerSecurityReferenceMonitorIPCManagerVirtualMemoryManager(VMM)ProcessManagerPnPManagerPowerManagerWindowManager GDIObject Manager - + .d2-2060964008 .fill-N1{fill:#0A0F25;} + .d2-2060964008 .fill-N2{fill:#676C7E;} + .d2-2060964008 .fill-N3{fill:#9499AB;} + .d2-2060964008 .fill-N4{fill:#CFD2DD;} + .d2-2060964008 .fill-N5{fill:#DEE1EB;} + .d2-2060964008 .fill-N6{fill:#EEF1F8;} + .d2-2060964008 .fill-N7{fill:#FFFFFF;} + .d2-2060964008 .fill-B1{fill:#0D32B2;} + .d2-2060964008 .fill-B2{fill:#0D32B2;} + .d2-2060964008 .fill-B3{fill:#E3E9FD;} + .d2-2060964008 .fill-B4{fill:#E3E9FD;} + .d2-2060964008 .fill-B5{fill:#EDF0FD;} + .d2-2060964008 .fill-B6{fill:#F7F8FE;} + .d2-2060964008 .fill-AA2{fill:#4A6FF3;} + .d2-2060964008 .fill-AA4{fill:#EDF0FD;} + .d2-2060964008 .fill-AA5{fill:#F7F8FE;} + .d2-2060964008 .fill-AB4{fill:#EDF0FD;} + .d2-2060964008 .fill-AB5{fill:#F7F8FE;} + .d2-2060964008 .stroke-N1{stroke:#0A0F25;} + .d2-2060964008 .stroke-N2{stroke:#676C7E;} + .d2-2060964008 .stroke-N3{stroke:#9499AB;} + .d2-2060964008 .stroke-N4{stroke:#CFD2DD;} + .d2-2060964008 .stroke-N5{stroke:#DEE1EB;} + .d2-2060964008 .stroke-N6{stroke:#EEF1F8;} + .d2-2060964008 .stroke-N7{stroke:#FFFFFF;} + .d2-2060964008 .stroke-B1{stroke:#0D32B2;} + .d2-2060964008 .stroke-B2{stroke:#0D32B2;} + .d2-2060964008 .stroke-B3{stroke:#E3E9FD;} + .d2-2060964008 .stroke-B4{stroke:#E3E9FD;} + .d2-2060964008 .stroke-B5{stroke:#EDF0FD;} + .d2-2060964008 .stroke-B6{stroke:#F7F8FE;} + .d2-2060964008 .stroke-AA2{stroke:#4A6FF3;} + .d2-2060964008 .stroke-AA4{stroke:#EDF0FD;} + .d2-2060964008 .stroke-AA5{stroke:#F7F8FE;} + .d2-2060964008 .stroke-AB4{stroke:#EDF0FD;} + .d2-2060964008 .stroke-AB5{stroke:#F7F8FE;} + .d2-2060964008 .background-color-N1{background-color:#0A0F25;} + .d2-2060964008 .background-color-N2{background-color:#676C7E;} + .d2-2060964008 .background-color-N3{background-color:#9499AB;} + .d2-2060964008 .background-color-N4{background-color:#CFD2DD;} + .d2-2060964008 .background-color-N5{background-color:#DEE1EB;} + .d2-2060964008 .background-color-N6{background-color:#EEF1F8;} + .d2-2060964008 .background-color-N7{background-color:#FFFFFF;} + .d2-2060964008 .background-color-B1{background-color:#0D32B2;} + .d2-2060964008 .background-color-B2{background-color:#0D32B2;} + .d2-2060964008 .background-color-B3{background-color:#E3E9FD;} + .d2-2060964008 .background-color-B4{background-color:#E3E9FD;} + .d2-2060964008 .background-color-B5{background-color:#EDF0FD;} + .d2-2060964008 .background-color-B6{background-color:#F7F8FE;} + .d2-2060964008 .background-color-AA2{background-color:#4A6FF3;} + .d2-2060964008 .background-color-AA4{background-color:#EDF0FD;} + .d2-2060964008 .background-color-AA5{background-color:#F7F8FE;} + .d2-2060964008 .background-color-AB4{background-color:#EDF0FD;} + .d2-2060964008 .background-color-AB5{background-color:#F7F8FE;} + .d2-2060964008 .color-N1{color:#0A0F25;} + .d2-2060964008 .color-N2{color:#676C7E;} + .d2-2060964008 .color-N3{color:#9499AB;} + .d2-2060964008 .color-N4{color:#CFD2DD;} + .d2-2060964008 .color-N5{color:#DEE1EB;} + .d2-2060964008 .color-N6{color:#EEF1F8;} + .d2-2060964008 .color-N7{color:#FFFFFF;} + .d2-2060964008 .color-B1{color:#0D32B2;} + .d2-2060964008 .color-B2{color:#0D32B2;} + .d2-2060964008 .color-B3{color:#E3E9FD;} + .d2-2060964008 .color-B4{color:#E3E9FD;} + .d2-2060964008 .color-B5{color:#EDF0FD;} + .d2-2060964008 .color-B6{color:#F7F8FE;} + .d2-2060964008 .color-AA2{color:#4A6FF3;} + .d2-2060964008 .color-AA4{color:#EDF0FD;} + .d2-2060964008 .color-AA5{color:#F7F8FE;} + .d2-2060964008 .color-AB4{color:#EDF0FD;} + .d2-2060964008 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>Executive ServicesI/OManagerSecurityReferenceMonitorIPCManagerVirtualMemoryManager(VMM)ProcessManagerPnPManagerPowerManagerWindowManager GDIObject Manager + \ No newline at end of file diff --git a/e2etests/testdata/stable/executive_grid/elk/board.exp.json b/e2etests/testdata/stable/executive_grid/elk/board.exp.json index b9f09e5b5..6ec7a989f 100644 --- a/e2etests/testdata/stable/executive_grid/elk/board.exp.json +++ b/e2etests/testdata/stable/executive_grid/elk/board.exp.json @@ -52,7 +52,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -93,7 +93,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -134,7 +134,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -175,7 +175,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -216,7 +216,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -257,7 +257,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -298,7 +298,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -339,7 +339,7 @@ "y": 101 }, "width": 100, - "height": 109, + "height": 200, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -377,7 +377,7 @@ "type": "rectangle", "pos": { "x": 0, - "y": 250 + "y": 341 }, "width": 1080, "height": 61, diff --git a/e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg b/e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg index 7ac1c0a8a..8b27b5168 100644 --- a/e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/executive_grid/elk/sketch.exp.svg @@ -1,9 +1,9 @@ -Executive ServicesI/OManagerSecurityReferenceMonitorIPCManagerVirtualMemoryManager(VMM)ProcessManagerPnPManagerPowerManagerWindowManager GDIObject Manager - + .d2-2060964008 .fill-N1{fill:#0A0F25;} + .d2-2060964008 .fill-N2{fill:#676C7E;} + .d2-2060964008 .fill-N3{fill:#9499AB;} + .d2-2060964008 .fill-N4{fill:#CFD2DD;} + .d2-2060964008 .fill-N5{fill:#DEE1EB;} + .d2-2060964008 .fill-N6{fill:#EEF1F8;} + .d2-2060964008 .fill-N7{fill:#FFFFFF;} + .d2-2060964008 .fill-B1{fill:#0D32B2;} + .d2-2060964008 .fill-B2{fill:#0D32B2;} + .d2-2060964008 .fill-B3{fill:#E3E9FD;} + .d2-2060964008 .fill-B4{fill:#E3E9FD;} + .d2-2060964008 .fill-B5{fill:#EDF0FD;} + .d2-2060964008 .fill-B6{fill:#F7F8FE;} + .d2-2060964008 .fill-AA2{fill:#4A6FF3;} + .d2-2060964008 .fill-AA4{fill:#EDF0FD;} + .d2-2060964008 .fill-AA5{fill:#F7F8FE;} + .d2-2060964008 .fill-AB4{fill:#EDF0FD;} + .d2-2060964008 .fill-AB5{fill:#F7F8FE;} + .d2-2060964008 .stroke-N1{stroke:#0A0F25;} + .d2-2060964008 .stroke-N2{stroke:#676C7E;} + .d2-2060964008 .stroke-N3{stroke:#9499AB;} + .d2-2060964008 .stroke-N4{stroke:#CFD2DD;} + .d2-2060964008 .stroke-N5{stroke:#DEE1EB;} + .d2-2060964008 .stroke-N6{stroke:#EEF1F8;} + .d2-2060964008 .stroke-N7{stroke:#FFFFFF;} + .d2-2060964008 .stroke-B1{stroke:#0D32B2;} + .d2-2060964008 .stroke-B2{stroke:#0D32B2;} + .d2-2060964008 .stroke-B3{stroke:#E3E9FD;} + .d2-2060964008 .stroke-B4{stroke:#E3E9FD;} + .d2-2060964008 .stroke-B5{stroke:#EDF0FD;} + .d2-2060964008 .stroke-B6{stroke:#F7F8FE;} + .d2-2060964008 .stroke-AA2{stroke:#4A6FF3;} + .d2-2060964008 .stroke-AA4{stroke:#EDF0FD;} + .d2-2060964008 .stroke-AA5{stroke:#F7F8FE;} + .d2-2060964008 .stroke-AB4{stroke:#EDF0FD;} + .d2-2060964008 .stroke-AB5{stroke:#F7F8FE;} + .d2-2060964008 .background-color-N1{background-color:#0A0F25;} + .d2-2060964008 .background-color-N2{background-color:#676C7E;} + .d2-2060964008 .background-color-N3{background-color:#9499AB;} + .d2-2060964008 .background-color-N4{background-color:#CFD2DD;} + .d2-2060964008 .background-color-N5{background-color:#DEE1EB;} + .d2-2060964008 .background-color-N6{background-color:#EEF1F8;} + .d2-2060964008 .background-color-N7{background-color:#FFFFFF;} + .d2-2060964008 .background-color-B1{background-color:#0D32B2;} + .d2-2060964008 .background-color-B2{background-color:#0D32B2;} + .d2-2060964008 .background-color-B3{background-color:#E3E9FD;} + .d2-2060964008 .background-color-B4{background-color:#E3E9FD;} + .d2-2060964008 .background-color-B5{background-color:#EDF0FD;} + .d2-2060964008 .background-color-B6{background-color:#F7F8FE;} + .d2-2060964008 .background-color-AA2{background-color:#4A6FF3;} + .d2-2060964008 .background-color-AA4{background-color:#EDF0FD;} + .d2-2060964008 .background-color-AA5{background-color:#F7F8FE;} + .d2-2060964008 .background-color-AB4{background-color:#EDF0FD;} + .d2-2060964008 .background-color-AB5{background-color:#F7F8FE;} + .d2-2060964008 .color-N1{color:#0A0F25;} + .d2-2060964008 .color-N2{color:#676C7E;} + .d2-2060964008 .color-N3{color:#9499AB;} + .d2-2060964008 .color-N4{color:#CFD2DD;} + .d2-2060964008 .color-N5{color:#DEE1EB;} + .d2-2060964008 .color-N6{color:#EEF1F8;} + .d2-2060964008 .color-N7{color:#FFFFFF;} + .d2-2060964008 .color-B1{color:#0D32B2;} + .d2-2060964008 .color-B2{color:#0D32B2;} + .d2-2060964008 .color-B3{color:#E3E9FD;} + .d2-2060964008 .color-B4{color:#E3E9FD;} + .d2-2060964008 .color-B5{color:#EDF0FD;} + .d2-2060964008 .color-B6{color:#F7F8FE;} + .d2-2060964008 .color-AA2{color:#4A6FF3;} + .d2-2060964008 .color-AA4{color:#EDF0FD;} + .d2-2060964008 .color-AA5{color:#F7F8FE;} + .d2-2060964008 .color-AB4{color:#EDF0FD;} + .d2-2060964008 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>Executive ServicesI/OManagerSecurityReferenceMonitorIPCManagerVirtualMemoryManager(VMM)ProcessManagerPnPManagerPowerManagerWindowManager GDIObject Manager + \ No newline at end of file From 04775c849168942277d02d20d40830dede51475d Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Tue, 4 Apr 2023 21:00:40 -0700 Subject: [PATCH 23/31] validate descendants --- d2compiler/compile.go | 6 ++++++ d2compiler/compile_test.go | 15 +++++++++++++++ .../d2compiler/TestCompile/grid_nested.exp.json | 16 ++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 testdata/d2compiler/TestCompile/grid_nested.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 0236a9ce2..aea9cbfa2 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -705,6 +705,12 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { if !in && arrowheadIn { c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid shape, can only set "%s" for arrowheads`, obj.Attributes.Shape.Value)) } + case "rows", "columns": + for _, child := range obj.ChildrenArray { + if child.IsContainer() { + c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid grid %#v. can only set %#v with no descendants (see %#v)`, obj.AbsID(), keyword, child.ChildrenArray[0].AbsID())) + } + } } return } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 4afc52fbf..570163653 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2303,6 +2303,21 @@ obj { d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge "c -> hey.b" cannot enter grid "hey" d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge "hey.a -> c" cannot enter grid "hey"`, }, + { + name: "grid_nested", + text: `hey: { + rows: 200 + columns: 200 + + a + b + c + d.invalid descendant +} +`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid "hey". can only set "rows" with no descendants (see "hey.d.invalid descendant") +d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid "hey". can only set "columns" with no descendants (see "hey.d.invalid descendant")`, + }, } for _, tc := range testCases { diff --git a/testdata/d2compiler/TestCompile/grid_nested.exp.json b/testdata/d2compiler/TestCompile/grid_nested.exp.json new file mode 100644 index 000000000..22f85db05 --- /dev/null +++ b/testdata/d2compiler/TestCompile/grid_nested.exp.json @@ -0,0 +1,16 @@ +{ + "graph": null, + "err": { + "ioerr": null, + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,1:1:8-1:10:17", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid \"hey\". can only set \"rows\" with no descendants (see \"hey.d.invalid descendant\")" + }, + { + "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,2:1:19-2:13:31", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid \"hey\". can only set \"columns\" with no descendants (see \"hey.d.invalid descendant\")" + } + ] + } +} From 44f2d7a47f395c0b072eae6ce88c918e6389f505 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 5 Apr 2023 11:03:04 -0700 Subject: [PATCH 24/31] update grid_tests --- e2etests/testdata/files/grid_tests.d2 | 15 + .../stable/grid_tests/dagre/board.exp.json | 410 ++++++++++++++++++ .../stable/grid_tests/dagre/sketch.exp.svg | 164 +++---- .../stable/grid_tests/elk/board.exp.json | 410 ++++++++++++++++++ .../stable/grid_tests/elk/sketch.exp.svg | 164 +++---- 5 files changed, 999 insertions(+), 164 deletions(-) diff --git a/e2etests/testdata/files/grid_tests.d2 b/e2etests/testdata/files/grid_tests.d2 index d4b02f841..501c9ea24 100644 --- a/e2etests/testdata/files/grid_tests.d2 +++ b/e2etests/testdata/files/grid_tests.d2 @@ -117,3 +117,18 @@ columns 3: { f g } + +widths heights: { + rows: 3 + columns: 3 + + a w200.width: 200 + b h300.height: 300 + c + d h200.height: 200 + e + f w400.width: 400 + g + h + i +} diff --git a/e2etests/testdata/stable/grid_tests/dagre/board.exp.json b/e2etests/testdata/stable/grid_tests/dagre/board.exp.json index 431f1dd28..a82de5acf 100644 --- a/e2etests/testdata/stable/grid_tests/dagre/board.exp.json +++ b/e2etests/testdata/stable/grid_tests/dagre/board.exp.json @@ -3282,6 +3282,416 @@ "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, "level": 2 + }, + { + "id": "widths heights", + "type": "rectangle", + "pos": { + "x": 4389, + "y": 28 + }, + "width": 886, + "height": 766, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "widths heights", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 171, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "widths heights.a w200", + "type": "rectangle", + "pos": { + "x": 4449, + "y": 88 + }, + "width": 200, + "height": 300, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a w200", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 49, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.b h300", + "type": "rectangle", + "pos": { + "x": 4689, + "y": 88 + }, + "width": 86, + "height": 300, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b h300", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 46, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.c", + "type": "rectangle", + "pos": { + "x": 4815, + "y": 88 + }, + "width": 400, + "height": 300, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.d h200", + "type": "rectangle", + "pos": { + "x": 4449, + "y": 428 + }, + "width": 200, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d h200", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 47, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.e", + "type": "rectangle", + "pos": { + "x": 4689, + "y": 428 + }, + "width": 86, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.f w400", + "type": "rectangle", + "pos": { + "x": 4815, + "y": 428 + }, + "width": 400, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f w400", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 46, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.g", + "type": "rectangle", + "pos": { + "x": 4449, + "y": 668 + }, + "width": 200, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.h", + "type": "rectangle", + "pos": { + "x": 4689, + "y": 668 + }, + "width": 86, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "h", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.i", + "type": "rectangle", + "pos": { + "x": 4815, + "y": 668 + }, + "width": 400, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "i", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 4, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 } ], "connections": [], diff --git a/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg b/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg index 9e87e99d6..43be0cd45 100644 --- a/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg @@ -1,17 +1,17 @@ -rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg - + .d2-433946113 .fill-N1{fill:#0A0F25;} + .d2-433946113 .fill-N2{fill:#676C7E;} + .d2-433946113 .fill-N3{fill:#9499AB;} + .d2-433946113 .fill-N4{fill:#CFD2DD;} + .d2-433946113 .fill-N5{fill:#DEE1EB;} + .d2-433946113 .fill-N6{fill:#EEF1F8;} + .d2-433946113 .fill-N7{fill:#FFFFFF;} + .d2-433946113 .fill-B1{fill:#0D32B2;} + .d2-433946113 .fill-B2{fill:#0D32B2;} + .d2-433946113 .fill-B3{fill:#E3E9FD;} + .d2-433946113 .fill-B4{fill:#E3E9FD;} + .d2-433946113 .fill-B5{fill:#EDF0FD;} + .d2-433946113 .fill-B6{fill:#F7F8FE;} + .d2-433946113 .fill-AA2{fill:#4A6FF3;} + .d2-433946113 .fill-AA4{fill:#EDF0FD;} + .d2-433946113 .fill-AA5{fill:#F7F8FE;} + .d2-433946113 .fill-AB4{fill:#EDF0FD;} + .d2-433946113 .fill-AB5{fill:#F7F8FE;} + .d2-433946113 .stroke-N1{stroke:#0A0F25;} + .d2-433946113 .stroke-N2{stroke:#676C7E;} + .d2-433946113 .stroke-N3{stroke:#9499AB;} + .d2-433946113 .stroke-N4{stroke:#CFD2DD;} + .d2-433946113 .stroke-N5{stroke:#DEE1EB;} + .d2-433946113 .stroke-N6{stroke:#EEF1F8;} + .d2-433946113 .stroke-N7{stroke:#FFFFFF;} + .d2-433946113 .stroke-B1{stroke:#0D32B2;} + .d2-433946113 .stroke-B2{stroke:#0D32B2;} + .d2-433946113 .stroke-B3{stroke:#E3E9FD;} + .d2-433946113 .stroke-B4{stroke:#E3E9FD;} + .d2-433946113 .stroke-B5{stroke:#EDF0FD;} + .d2-433946113 .stroke-B6{stroke:#F7F8FE;} + .d2-433946113 .stroke-AA2{stroke:#4A6FF3;} + .d2-433946113 .stroke-AA4{stroke:#EDF0FD;} + .d2-433946113 .stroke-AA5{stroke:#F7F8FE;} + .d2-433946113 .stroke-AB4{stroke:#EDF0FD;} + .d2-433946113 .stroke-AB5{stroke:#F7F8FE;} + .d2-433946113 .background-color-N1{background-color:#0A0F25;} + .d2-433946113 .background-color-N2{background-color:#676C7E;} + .d2-433946113 .background-color-N3{background-color:#9499AB;} + .d2-433946113 .background-color-N4{background-color:#CFD2DD;} + .d2-433946113 .background-color-N5{background-color:#DEE1EB;} + .d2-433946113 .background-color-N6{background-color:#EEF1F8;} + .d2-433946113 .background-color-N7{background-color:#FFFFFF;} + .d2-433946113 .background-color-B1{background-color:#0D32B2;} + .d2-433946113 .background-color-B2{background-color:#0D32B2;} + .d2-433946113 .background-color-B3{background-color:#E3E9FD;} + .d2-433946113 .background-color-B4{background-color:#E3E9FD;} + .d2-433946113 .background-color-B5{background-color:#EDF0FD;} + .d2-433946113 .background-color-B6{background-color:#F7F8FE;} + .d2-433946113 .background-color-AA2{background-color:#4A6FF3;} + .d2-433946113 .background-color-AA4{background-color:#EDF0FD;} + .d2-433946113 .background-color-AA5{background-color:#F7F8FE;} + .d2-433946113 .background-color-AB4{background-color:#EDF0FD;} + .d2-433946113 .background-color-AB5{background-color:#F7F8FE;} + .d2-433946113 .color-N1{color:#0A0F25;} + .d2-433946113 .color-N2{color:#676C7E;} + .d2-433946113 .color-N3{color:#9499AB;} + .d2-433946113 .color-N4{color:#CFD2DD;} + .d2-433946113 .color-N5{color:#DEE1EB;} + .d2-433946113 .color-N6{color:#EEF1F8;} + .d2-433946113 .color-N7{color:#FFFFFF;} + .d2-433946113 .color-B1{color:#0D32B2;} + .d2-433946113 .color-B2{color:#0D32B2;} + .d2-433946113 .color-B3{color:#E3E9FD;} + .d2-433946113 .color-B4{color:#E3E9FD;} + .d2-433946113 .color-B5{color:#EDF0FD;} + .d2-433946113 .color-B6{color:#F7F8FE;} + .d2-433946113 .color-AA2{color:#4A6FF3;} + .d2-433946113 .color-AA4{color:#EDF0FD;} + .d2-433946113 .color-AA5{color:#F7F8FE;} + .d2-433946113 .color-AB4{color:#EDF0FD;} + .d2-433946113 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3widths heightsabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga w200b h300cd h200ef w400ghi + \ No newline at end of file diff --git a/e2etests/testdata/stable/grid_tests/elk/board.exp.json b/e2etests/testdata/stable/grid_tests/elk/board.exp.json index e1fd68bee..bb7e1930e 100644 --- a/e2etests/testdata/stable/grid_tests/elk/board.exp.json +++ b/e2etests/testdata/stable/grid_tests/elk/board.exp.json @@ -3282,6 +3282,416 @@ "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, "level": 2 + }, + { + "id": "widths heights", + "type": "rectangle", + "pos": { + "x": 4001, + "y": 40 + }, + "width": 886, + "height": 766, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "widths heights", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 171, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "widths heights.a w200", + "type": "rectangle", + "pos": { + "x": 4061, + "y": 100 + }, + "width": 200, + "height": 300, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a w200", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 49, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.b h300", + "type": "rectangle", + "pos": { + "x": 4301, + "y": 100 + }, + "width": 86, + "height": 300, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "b h300", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 46, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.c", + "type": "rectangle", + "pos": { + "x": 4427, + "y": 100 + }, + "width": 400, + "height": 300, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "c", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.d h200", + "type": "rectangle", + "pos": { + "x": 4061, + "y": 440 + }, + "width": 200, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "d h200", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 47, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.e", + "type": "rectangle", + "pos": { + "x": 4301, + "y": 440 + }, + "width": 86, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "e", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.f w400", + "type": "rectangle", + "pos": { + "x": 4427, + "y": 440 + }, + "width": 400, + "height": 200, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "f w400", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 46, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.g", + "type": "rectangle", + "pos": { + "x": 4061, + "y": 680 + }, + "width": 200, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "g", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 9, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.h", + "type": "rectangle", + "pos": { + "x": 4301, + "y": 680 + }, + "width": 86, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "h", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 8, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "widths heights.i", + "type": "rectangle", + "pos": { + "x": 4427, + "y": 680 + }, + "width": 400, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "i", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 4, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 } ], "connections": [], diff --git a/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg b/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg index 0004db37f..bfcf25d48 100644 --- a/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg @@ -1,17 +1,17 @@ -rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg - + .d2-253581586 .fill-N1{fill:#0A0F25;} + .d2-253581586 .fill-N2{fill:#676C7E;} + .d2-253581586 .fill-N3{fill:#9499AB;} + .d2-253581586 .fill-N4{fill:#CFD2DD;} + .d2-253581586 .fill-N5{fill:#DEE1EB;} + .d2-253581586 .fill-N6{fill:#EEF1F8;} + .d2-253581586 .fill-N7{fill:#FFFFFF;} + .d2-253581586 .fill-B1{fill:#0D32B2;} + .d2-253581586 .fill-B2{fill:#0D32B2;} + .d2-253581586 .fill-B3{fill:#E3E9FD;} + .d2-253581586 .fill-B4{fill:#E3E9FD;} + .d2-253581586 .fill-B5{fill:#EDF0FD;} + .d2-253581586 .fill-B6{fill:#F7F8FE;} + .d2-253581586 .fill-AA2{fill:#4A6FF3;} + .d2-253581586 .fill-AA4{fill:#EDF0FD;} + .d2-253581586 .fill-AA5{fill:#F7F8FE;} + .d2-253581586 .fill-AB4{fill:#EDF0FD;} + .d2-253581586 .fill-AB5{fill:#F7F8FE;} + .d2-253581586 .stroke-N1{stroke:#0A0F25;} + .d2-253581586 .stroke-N2{stroke:#676C7E;} + .d2-253581586 .stroke-N3{stroke:#9499AB;} + .d2-253581586 .stroke-N4{stroke:#CFD2DD;} + .d2-253581586 .stroke-N5{stroke:#DEE1EB;} + .d2-253581586 .stroke-N6{stroke:#EEF1F8;} + .d2-253581586 .stroke-N7{stroke:#FFFFFF;} + .d2-253581586 .stroke-B1{stroke:#0D32B2;} + .d2-253581586 .stroke-B2{stroke:#0D32B2;} + .d2-253581586 .stroke-B3{stroke:#E3E9FD;} + .d2-253581586 .stroke-B4{stroke:#E3E9FD;} + .d2-253581586 .stroke-B5{stroke:#EDF0FD;} + .d2-253581586 .stroke-B6{stroke:#F7F8FE;} + .d2-253581586 .stroke-AA2{stroke:#4A6FF3;} + .d2-253581586 .stroke-AA4{stroke:#EDF0FD;} + .d2-253581586 .stroke-AA5{stroke:#F7F8FE;} + .d2-253581586 .stroke-AB4{stroke:#EDF0FD;} + .d2-253581586 .stroke-AB5{stroke:#F7F8FE;} + .d2-253581586 .background-color-N1{background-color:#0A0F25;} + .d2-253581586 .background-color-N2{background-color:#676C7E;} + .d2-253581586 .background-color-N3{background-color:#9499AB;} + .d2-253581586 .background-color-N4{background-color:#CFD2DD;} + .d2-253581586 .background-color-N5{background-color:#DEE1EB;} + .d2-253581586 .background-color-N6{background-color:#EEF1F8;} + .d2-253581586 .background-color-N7{background-color:#FFFFFF;} + .d2-253581586 .background-color-B1{background-color:#0D32B2;} + .d2-253581586 .background-color-B2{background-color:#0D32B2;} + .d2-253581586 .background-color-B3{background-color:#E3E9FD;} + .d2-253581586 .background-color-B4{background-color:#E3E9FD;} + .d2-253581586 .background-color-B5{background-color:#EDF0FD;} + .d2-253581586 .background-color-B6{background-color:#F7F8FE;} + .d2-253581586 .background-color-AA2{background-color:#4A6FF3;} + .d2-253581586 .background-color-AA4{background-color:#EDF0FD;} + .d2-253581586 .background-color-AA5{background-color:#F7F8FE;} + .d2-253581586 .background-color-AB4{background-color:#EDF0FD;} + .d2-253581586 .background-color-AB5{background-color:#F7F8FE;} + .d2-253581586 .color-N1{color:#0A0F25;} + .d2-253581586 .color-N2{color:#676C7E;} + .d2-253581586 .color-N3{color:#9499AB;} + .d2-253581586 .color-N4{color:#CFD2DD;} + .d2-253581586 .color-N5{color:#DEE1EB;} + .d2-253581586 .color-N6{color:#EEF1F8;} + .d2-253581586 .color-N7{color:#FFFFFF;} + .d2-253581586 .color-B1{color:#0D32B2;} + .d2-253581586 .color-B2{color:#0D32B2;} + .d2-253581586 .color-B3{color:#E3E9FD;} + .d2-253581586 .color-B4{color:#E3E9FD;} + .d2-253581586 .color-B5{color:#EDF0FD;} + .d2-253581586 .color-B6{color:#F7F8FE;} + .d2-253581586 .color-AA2{color:#4A6FF3;} + .d2-253581586 .color-AA4{color:#EDF0FD;} + .d2-253581586 .color-AA5{color:#F7F8FE;} + .d2-253581586 .color-AB4{color:#EDF0FD;} + .d2-253581586 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3widths heightsabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga w200b h300cd h200ef w400ghi + \ No newline at end of file From 06a942cf99fc0ff3189e8320cb687e57174e6a2d Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 5 Apr 2023 11:11:31 -0700 Subject: [PATCH 25/31] rename to grid diagram --- d2compiler/compile.go | 10 +- d2compiler/compile_test.go | 10 +- d2graph/{grid.go => grid_diagram.go} | 8 +- d2layouts/d2grid/{grid.go => grid_diagram.go} | 46 +++--- d2layouts/d2grid/layout.go | 144 +++++++++--------- .../d2compiler/TestCompile/grid_edge.exp.json | 6 +- .../TestCompile/grid_nested.exp.json | 4 +- 7 files changed, 114 insertions(+), 114 deletions(-) rename d2graph/{grid.go => grid_diagram.go} (54%) rename d2layouts/d2grid/{grid.go => grid_diagram.go} (71%) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index aea9cbfa2..c1a252440 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -708,7 +708,7 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { case "rows", "columns": for _, child := range obj.ChildrenArray { if child.IsContainer() { - c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid grid %#v. can only set %#v with no descendants (see %#v)`, obj.AbsID(), keyword, child.ChildrenArray[0].AbsID())) + c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid grid diagram %#v. can only set %#v with no descendants (see %#v)`, obj.AbsID(), keyword, child.ChildrenArray[0].AbsID())) } } } @@ -796,12 +796,12 @@ func (c *compiler) validateNear(g *d2graph.Graph) { func (c *compiler) validateEdges(g *d2graph.Graph) { for _, edge := range g.Edges { - if grid := edge.Src.ClosestGrid(); grid != nil { - c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid %#v", d2format.Format(edge.GetAstEdge()), grid.AbsID()) + if gd := edge.Src.ClosestGridDiagram(); gd != nil { + c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid diagram %#v", d2format.Format(edge.GetAstEdge()), gd.AbsID()) continue } - if grid := edge.Dst.ClosestGrid(); grid != nil { - c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid %#v", d2format.Format(edge.GetAstEdge()), grid.AbsID()) + if gd := edge.Dst.ClosestGridDiagram(); gd != nil { + c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid diagram %#v", d2format.Format(edge.GetAstEdge()), gd.AbsID()) continue } } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 570163653..a031203ea 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2299,9 +2299,9 @@ obj { hey -> c: ok `, - expErr: `d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge "a -> b" cannot enter grid "hey" -d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge "c -> hey.b" cannot enter grid "hey" -d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge "hey.a -> c" cannot enter grid "hey"`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge "a -> b" cannot enter grid diagram "hey" +d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge "c -> hey.b" cannot enter grid diagram "hey" +d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge "hey.a -> c" cannot enter grid diagram "hey"`, }, { name: "grid_nested", @@ -2315,8 +2315,8 @@ d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge "hey.a -> c" cannot en d.invalid descendant } `, - expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid "hey". can only set "rows" with no descendants (see "hey.d.invalid descendant") -d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid "hey". can only set "columns" with no descendants (see "hey.d.invalid descendant")`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid diagram "hey". can only set "rows" with no descendants (see "hey.d.invalid descendant") +d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid diagram "hey". can only set "columns" with no descendants (see "hey.d.invalid descendant")`, }, } diff --git a/d2graph/grid.go b/d2graph/grid_diagram.go similarity index 54% rename from d2graph/grid.go rename to d2graph/grid_diagram.go index 0315fe60b..ec41e0460 100644 --- a/d2graph/grid.go +++ b/d2graph/grid_diagram.go @@ -1,16 +1,16 @@ package d2graph -func (obj *Object) IsGrid() bool { +func (obj *Object) IsGridDiagram() bool { return obj != nil && obj.Attributes != nil && (obj.Attributes.Rows != nil || obj.Attributes.Columns != nil) } -func (obj *Object) ClosestGrid() *Object { +func (obj *Object) ClosestGridDiagram() *Object { if obj.Parent == nil { return nil } - if obj.Parent.IsGrid() { + if obj.Parent.IsGridDiagram() { return obj.Parent } - return obj.Parent.ClosestGrid() + return obj.Parent.ClosestGridDiagram() } diff --git a/d2layouts/d2grid/grid.go b/d2layouts/d2grid/grid_diagram.go similarity index 71% rename from d2layouts/d2grid/grid.go rename to d2layouts/d2grid/grid_diagram.go index f5d6e7b65..c26a6e917 100644 --- a/d2layouts/d2grid/grid.go +++ b/d2layouts/d2grid/grid_diagram.go @@ -6,7 +6,7 @@ import ( "oss.terrastruct.com/d2/d2graph" ) -type grid struct { +type gridDiagram struct { root *d2graph.Object nodes []*d2graph.Object rows int @@ -18,24 +18,24 @@ type grid struct { height float64 } -func newGrid(root *d2graph.Object) *grid { - g := grid{root: root, nodes: root.ChildrenArray} +func newGridDiagram(root *d2graph.Object) *gridDiagram { + gd := gridDiagram{root: root, nodes: root.ChildrenArray} if root.Attributes.Rows != nil { - g.rows, _ = strconv.Atoi(root.Attributes.Rows.Value) + gd.rows, _ = strconv.Atoi(root.Attributes.Rows.Value) } if root.Attributes.Columns != nil { - g.columns, _ = strconv.Atoi(root.Attributes.Columns.Value) + gd.columns, _ = strconv.Atoi(root.Attributes.Columns.Value) } // compute exact row/column count based on values entered - if g.columns == 0 { - g.rowDominant = true - } else if g.rows == 0 { - g.rowDominant = false + if gd.columns == 0 { + gd.rowDominant = true + } else if gd.rows == 0 { + gd.rowDominant = false } else { // if keyword rows is first, rows are primary, columns secondary. if root.Attributes.Rows.MapKey.Range.Before(root.Attributes.Columns.MapKey.Range) { - g.rowDominant = true + gd.rowDominant = true } // rows and columns specified, but we want to continue naturally if user enters more nodes @@ -48,34 +48,34 @@ func newGrid(root *d2graph.Object) *grid { // . └───────┘ ▲ │ └───────┘ ▲ // . ▲ └─existing nodes modified │ ▲ └─existing nodes preserved // . └─existing rows preserved │ └─existing rows modified - capacity := g.rows * g.columns - for capacity < len(g.nodes) { - if g.rowDominant { - g.rows++ - capacity += g.columns + capacity := gd.rows * gd.columns + for capacity < len(gd.nodes) { + if gd.rowDominant { + gd.rows++ + capacity += gd.columns } else { - g.columns++ - capacity += g.rows + gd.columns++ + capacity += gd.rows } } } - return &g + return &gd } -func (g *grid) shift(dx, dy float64) { - for _, obj := range g.nodes { +func (gd *gridDiagram) shift(dx, dy float64) { + for _, obj := range gd.nodes { obj.TopLeft.X += dx obj.TopLeft.Y += dy } } -func (g *grid) cleanup(obj *d2graph.Object, graph *d2graph.Graph) { +func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) { obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = make([]*d2graph.Object, 0) - for _, child := range g.nodes { + for _, child := range gd.nodes { obj.Children[child.ID] = child obj.ChildrenArray = append(obj.ChildrenArray, child) } - graph.Objects = append(graph.Objects, g.nodes...) + graph.Objects = append(graph.Objects, gd.nodes...) } diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 3bdc0a4be..0b42714af 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -29,25 +29,25 @@ const ( // 7. Put grid children back in correct location func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d2graph.LayoutGraph { return func(ctx context.Context, g *d2graph.Graph) error { - grids, objectOrder, err := withoutGrids(ctx, g) + gridDiagrams, objectOrder, err := withoutGridDiagrams(ctx, g) if err != nil { return err } - if g.Root.IsGrid() && len(g.Root.ChildrenArray) != 0 { + if g.Root.IsGridDiagram() && len(g.Root.ChildrenArray) != 0 { g.Root.TopLeft = geo.NewPoint(0, 0) } else if err := layout(ctx, g); err != nil { return err } - cleanup(g, grids, objectOrder) + cleanup(g, gridDiagrams, objectOrder) return nil } } -func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*grid, objectOrder map[string]int, err error) { +func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph) (gridDiagrams map[string]*gridDiagram, objectOrder map[string]int, err error) { toRemove := make(map[*d2graph.Object]struct{}) - grids := make(map[string]*grid) + gridDiagrams = make(map[string]*gridDiagram) if len(g.Objects) > 0 { queue := make([]*d2graph.Object, 1, len(g.Objects)) @@ -58,12 +58,12 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g if len(obj.ChildrenArray) == 0 { continue } - if !obj.IsGrid() { + if !obj.IsGridDiagram() { queue = append(queue, obj.ChildrenArray...) continue } - grid, err := layoutGrid(g, obj) + gd, err := layoutGrid(g, obj) if err != nil { return nil, nil, err } @@ -71,13 +71,13 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g obj.ChildrenArray = nil var dx, dy float64 - width := grid.width + 2*CONTAINER_PADDING + width := gd.width + 2*CONTAINER_PADDING labelWidth := float64(obj.LabelDimensions.Width) + 2*label.PADDING if labelWidth > width { dx = (labelWidth - width) / 2 width = labelWidth } - height := grid.height + 2*CONTAINER_PADDING + height := gd.height + 2*CONTAINER_PADDING labelHeight := float64(obj.LabelDimensions.Height) + 2*label.PADDING if labelHeight > CONTAINER_PADDING { // if the label doesn't fit within the padding, we need to add more @@ -87,14 +87,14 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g } // we need to center children if we have to expand to fit the container label if dx != 0 || dy != 0 { - grid.shift(dx, dy) + gd.shift(dx, dy) } obj.Box = geo.NewBox(nil, width, height) obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) - grids[obj.AbsID()] = grid + gridDiagrams[obj.AbsID()] = gd - for _, node := range grid.nodes { + for _, node := range gd.nodes { toRemove[node] = struct{}{} } } @@ -110,20 +110,20 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g } g.Objects = layoutObjects - return grids, objectOrder, nil + return gridDiagrams, objectOrder, nil } -func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { - grid := newGrid(obj) +func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) { + gd := newGridDiagram(obj) - if grid.rows != 0 && grid.columns != 0 { - grid.layoutEvenly(g, obj) + if gd.rows != 0 && gd.columns != 0 { + gd.layoutEvenly(g, obj) } else { - grid.layoutDynamic(g, obj) + gd.layoutDynamic(g, obj) } // position labels and icons - for _, n := range grid.nodes { + for _, n := range gd.nodes { if n.Attributes.Icon != nil { n.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) n.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) @@ -132,32 +132,32 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) { } } - return grid, nil + return gd, nil } -func (grid *grid) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { +func (gd *gridDiagram) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { // layout nodes in a grid with these 2 properties: // all nodes in the same row should have the same height // all nodes in the same column should have the same width getNode := func(rowIndex, columnIndex int) *d2graph.Object { var index int - if grid.rowDominant { - index = rowIndex*grid.columns + columnIndex + if gd.rowDominant { + index = rowIndex*gd.columns + columnIndex } else { - index = columnIndex*grid.rows + rowIndex + index = columnIndex*gd.rows + rowIndex } - if index < len(grid.nodes) { - return grid.nodes[index] + if index < len(gd.nodes) { + return gd.nodes[index] } return nil } - rowHeights := make([]float64, 0, grid.rows) - colWidths := make([]float64, 0, grid.columns) - for i := 0; i < grid.rows; i++ { + rowHeights := make([]float64, 0, gd.rows) + colWidths := make([]float64, 0, gd.columns) + for i := 0; i < gd.rows; i++ { rowHeight := 0. - for j := 0; j < grid.columns; j++ { + for j := 0; j < gd.columns; j++ { n := getNode(i, j) if n == nil { break @@ -166,9 +166,9 @@ func (grid *grid) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { } rowHeights = append(rowHeights, rowHeight) } - for j := 0; j < grid.columns; j++ { + for j := 0; j < gd.columns; j++ { columnWidth := 0. - for i := 0; i < grid.rows; i++ { + for i := 0; i < gd.rows; i++ { n := getNode(i, j) if n == nil { break @@ -179,9 +179,9 @@ func (grid *grid) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { } cursor := geo.NewPoint(0, 0) - if grid.rowDominant { - for i := 0; i < grid.rows; i++ { - for j := 0; j < grid.columns; j++ { + if gd.rowDominant { + for i := 0; i < gd.rows; i++ { + for j := 0; j < gd.columns; j++ { n := getNode(i, j) if n == nil { break @@ -195,8 +195,8 @@ func (grid *grid) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { cursor.Y += rowHeights[i] + VERTICAL_PAD } } else { - for j := 0; j < grid.columns; j++ { - for i := 0; i < grid.rows; i++ { + for j := 0; j < gd.columns; j++ { + for i := 0; i < gd.rows; i++ { n := getNode(i, j) if n == nil { break @@ -220,11 +220,11 @@ func (grid *grid) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { } totalWidth -= HORIZONTAL_PAD totalHeight -= VERTICAL_PAD - grid.width = totalWidth - grid.height = totalHeight + gd.width = totalWidth + gd.height = totalHeight } -func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { +func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { // assume we have the following nodes to layout: // . ┌A──────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐ // . └───────────────┘ │ │ │ │ │ │ │ │ @@ -242,16 +242,16 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { // we want to split up the total width across the N rows or columns as evenly as possible var totalWidth, totalHeight float64 - for _, n := range grid.nodes { + for _, n := range gd.nodes { totalWidth += n.Width totalHeight += n.Height } - totalWidth += HORIZONTAL_PAD * float64(len(grid.nodes)-1) - totalHeight += VERTICAL_PAD * float64(len(grid.nodes)-1) + totalWidth += HORIZONTAL_PAD * float64(len(gd.nodes)-1) + totalHeight += VERTICAL_PAD * float64(len(gd.nodes)-1) layout := [][]int{{}} - if grid.rowDominant { - targetWidth := totalWidth / float64(grid.rows) + if gd.rowDominant { + targetWidth := totalWidth / float64(gd.rows) rowWidth := 0. rowIndex := 0 addRow := func() { @@ -264,7 +264,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { rowWidth += n.Width + HORIZONTAL_PAD } - for i, n := range grid.nodes { + for i, n := range gd.nodes { // if the next node will be past the target, start a new row if rowWidth+n.Width+HORIZONTAL_PAD > targetWidth { // if the node is mostly past the target, put it on the next row @@ -273,7 +273,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { addNode(i, n) } else { addNode(i, n) - if i < len(grid.nodes)-1 { + if i < len(gd.nodes)-1 { addRow() } } @@ -282,7 +282,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { } } } else { - targetHeight := totalHeight / float64(grid.columns) + targetHeight := totalHeight / float64(gd.columns) colHeight := 0. colIndex := 0 addCol := func() { @@ -295,7 +295,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { colHeight += n.Height + VERTICAL_PAD } - for i, n := range grid.nodes { + for i, n := range gd.nodes { // if the next node will be past the target, start a new row if colHeight+n.Height+VERTICAL_PAD > targetHeight { // if the node is mostly past the target, put it on the next row @@ -304,7 +304,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { addNode(i, n) } else { addNode(i, n) - if i < len(grid.nodes)-1 { + if i < len(gd.nodes)-1 { addCol() } } @@ -316,7 +316,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { cursor := geo.NewPoint(0, 0) var maxY, maxX float64 - if grid.rowDominant { + if gd.rowDominant { // if we have 2 rows, then each row's nodes should have the same height // . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C) // . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │ @@ -333,7 +333,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { for _, row := range layout { rowHeight := 0. for _, nodeIndex := range row { - n := grid.nodes[nodeIndex] + n := gd.nodes[nodeIndex] n.TopLeft = cursor.Copy() cursor.X += n.Width + HORIZONTAL_PAD rowHeight = math.Max(rowHeight, n.Height) @@ -344,7 +344,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { // set all nodes in row to the same height for _, nodeIndex := range row { - n := grid.nodes[nodeIndex] + n := gd.nodes[nodeIndex] n.Height = rowHeight } @@ -375,7 +375,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { nodes := []*d2graph.Object{} var widest float64 for _, nodeIndex := range row { - n := grid.nodes[nodeIndex] + n := gd.nodes[nodeIndex] widest = math.Max(widest, n.Width) nodes = append(nodes, n) } @@ -387,7 +387,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if n.Width < widest { var index int for i, nodeIndex := range row { - if n == grid.nodes[nodeIndex] { + if n == gd.nodes[nodeIndex] { index = i break } @@ -396,7 +396,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { n.Width += grow // shift following nodes for i := index + 1; i < len(row); i++ { - grid.nodes[row[i]].TopLeft.X += grow + gd.nodes[row[i]].TopLeft.X += grow } delta -= grow if delta <= 0 { @@ -407,7 +407,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if delta > 0 { grow := delta / float64(len(row)) for i := len(row) - 1; i >= 0; i-- { - n := grid.nodes[row[i]] + n := gd.nodes[row[i]] n.TopLeft.X += grow * float64(i) n.Width += grow delta -= grow @@ -430,7 +430,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { for _, column := range layout { colWidth := 0. for _, nodeIndex := range column { - n := grid.nodes[nodeIndex] + n := gd.nodes[nodeIndex] n.TopLeft = cursor.Copy() cursor.Y += n.Height + VERTICAL_PAD colWidth = math.Max(colWidth, n.Width) @@ -440,7 +440,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { maxY = math.Max(maxY, colHeight) // set all nodes in column to the same width for _, nodeIndex := range column { - n := grid.nodes[nodeIndex] + n := gd.nodes[nodeIndex] n.Width = colWidth } @@ -469,7 +469,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { nodes := []*d2graph.Object{} var tallest float64 for _, nodeIndex := range column { - n := grid.nodes[nodeIndex] + n := gd.nodes[nodeIndex] tallest = math.Max(tallest, n.Height) nodes = append(nodes, n) } @@ -481,7 +481,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if n.Height < tallest { var index int for i, nodeIndex := range column { - if n == grid.nodes[nodeIndex] { + if n == gd.nodes[nodeIndex] { index = i break } @@ -490,7 +490,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { n.Height += grow // shift following nodes for i := index + 1; i < len(column); i++ { - grid.nodes[column[i]].TopLeft.Y += grow + gd.nodes[column[i]].TopLeft.Y += grow } delta -= grow if delta <= 0 { @@ -501,7 +501,7 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if delta > 0 { grow := delta / float64(len(column)) for i := len(column) - 1; i >= 0; i-- { - n := grid.nodes[column[i]] + n := gd.nodes[column[i]] n.TopLeft.Y += grow * float64(i) n.Height += grow delta -= grow @@ -509,40 +509,40 @@ func (grid *grid) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { } } } - grid.width = maxX - grid.height = maxY + gd.width = maxX + gd.height = maxY } // cleanup restores the graph after the core layout engine finishes // - translating the grid to its position placed by the core layout engine // - restore the children of the grid // - sorts objects to their original graph order -func cleanup(graph *d2graph.Graph, grids map[string]*grid, objectsOrder map[string]int) { +func cleanup(graph *d2graph.Graph, gridDiagrams map[string]*gridDiagram, objectsOrder map[string]int) { defer func() { sort.SliceStable(graph.Objects, func(i, j int) bool { return objectsOrder[graph.Objects[i].AbsID()] < objectsOrder[graph.Objects[j].AbsID()] }) }() - if graph.Root.IsGrid() { - grid, exists := grids[graph.Root.AbsID()] + if graph.Root.IsGridDiagram() { + gd, exists := gridDiagrams[graph.Root.AbsID()] if exists { - grid.cleanup(graph.Root, graph) + gd.cleanup(graph.Root, graph) return } } for _, obj := range graph.Objects { - grid, exists := grids[obj.AbsID()] + gd, exists := gridDiagrams[obj.AbsID()] if !exists { continue } obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) // shift the grid from (0, 0) - grid.shift( + gd.shift( obj.TopLeft.X+CONTAINER_PADDING, obj.TopLeft.Y+CONTAINER_PADDING, ) - grid.cleanup(obj, graph) + gd.cleanup(obj, graph) } } diff --git a/testdata/d2compiler/TestCompile/grid_edge.exp.json b/testdata/d2compiler/TestCompile/grid_edge.exp.json index 1d6c84181..dee805205 100644 --- a/testdata/d2compiler/TestCompile/grid_edge.exp.json +++ b/testdata/d2compiler/TestCompile/grid_edge.exp.json @@ -5,15 +5,15 @@ "errs": [ { "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,2:1:17-2:7:23", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge \"a -> b\" cannot enter grid \"hey\"" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge \"a -> b\" cannot enter grid diagram \"hey\"" }, { "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,4:1:27-4:11:37", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge \"c -> hey.b\" cannot enter grid \"hey\"" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge \"c -> hey.b\" cannot enter grid diagram \"hey\"" }, { "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,5:1:39-5:11:49", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge \"hey.a -> c\" cannot enter grid \"hey\"" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge \"hey.a -> c\" cannot enter grid diagram \"hey\"" } ] } diff --git a/testdata/d2compiler/TestCompile/grid_nested.exp.json b/testdata/d2compiler/TestCompile/grid_nested.exp.json index 22f85db05..a45781692 100644 --- a/testdata/d2compiler/TestCompile/grid_nested.exp.json +++ b/testdata/d2compiler/TestCompile/grid_nested.exp.json @@ -5,11 +5,11 @@ "errs": [ { "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,1:1:8-1:10:17", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid \"hey\". can only set \"rows\" with no descendants (see \"hey.d.invalid descendant\")" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid diagram \"hey\". can only set \"rows\" with no descendants (see \"hey.d.invalid descendant\")" }, { "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,2:1:19-2:13:31", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid \"hey\". can only set \"columns\" with no descendants (see \"hey.d.invalid descendant\")" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid diagram \"hey\". can only set \"columns\" with no descendants (see \"hey.d.invalid descendant\")" } ] } From 292ac05a9e0e46561c6626bfcfe599aeb43f66a4 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 5 Apr 2023 11:33:28 -0700 Subject: [PATCH 26/31] changelog --- ci/release/changelogs/next.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 5651bfee0..da0c40910 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -1,6 +1,7 @@ #### Features 🚀 - Multi-board SVG outputs with internal links go to their output paths [#1116](https://github.com/terrastruct/d2/pull/1116) +- New grid layout to place nodes in rows and columns [#1122](https://github.com/terrastruct/d2/pull/1122) #### Improvements 🧹 From 8eb99a46c6032694b83b8f0d551f3e0e8eeec288 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 5 Apr 2023 11:49:04 -0700 Subject: [PATCH 27/31] new method for placing nodes across rows --- d2layouts/d2grid/layout.go | 192 +++++++++++++++++++++---------------- 1 file changed, 111 insertions(+), 81 deletions(-) diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 0b42714af..bdfab8f98 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -246,72 +246,16 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { totalWidth += n.Width totalHeight += n.Height } - totalWidth += HORIZONTAL_PAD * float64(len(gd.nodes)-1) - totalHeight += VERTICAL_PAD * float64(len(gd.nodes)-1) + totalWidth += HORIZONTAL_PAD * float64(len(gd.nodes)-gd.rows) + totalHeight += VERTICAL_PAD * float64(len(gd.nodes)-gd.columns) - layout := [][]int{{}} + var layout [][]*d2graph.Object if gd.rowDominant { targetWidth := totalWidth / float64(gd.rows) - rowWidth := 0. - rowIndex := 0 - addRow := func() { - layout = append(layout, []int{}) - rowIndex++ - rowWidth = 0 - } - addNode := func(i int, n *d2graph.Object) { - layout[rowIndex] = append(layout[rowIndex], i) - rowWidth += n.Width + HORIZONTAL_PAD - } - - for i, n := range gd.nodes { - // if the next node will be past the target, start a new row - if rowWidth+n.Width+HORIZONTAL_PAD > targetWidth { - // if the node is mostly past the target, put it on the next row - if rowWidth+n.Width/2 > targetWidth { - addRow() - addNode(i, n) - } else { - addNode(i, n) - if i < len(gd.nodes)-1 { - addRow() - } - } - } else { - addNode(i, n) - } - } + layout = gd.getBestLayout(targetWidth, false) } else { targetHeight := totalHeight / float64(gd.columns) - colHeight := 0. - colIndex := 0 - addCol := func() { - layout = append(layout, []int{}) - colIndex++ - colHeight = 0 - } - addNode := func(i int, n *d2graph.Object) { - layout[colIndex] = append(layout[colIndex], i) - colHeight += n.Height + VERTICAL_PAD - } - - for i, n := range gd.nodes { - // if the next node will be past the target, start a new row - if colHeight+n.Height+VERTICAL_PAD > targetHeight { - // if the node is mostly past the target, put it on the next row - if colHeight+n.Height/2 > targetHeight { - addCol() - addNode(i, n) - } else { - addNode(i, n) - if i < len(gd.nodes)-1 { - addCol() - } - } - } else { - addNode(i, n) - } - } + layout = gd.getBestLayout(targetHeight, true) } cursor := geo.NewPoint(0, 0) @@ -332,8 +276,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { rowWidths := []float64{} for _, row := range layout { rowHeight := 0. - for _, nodeIndex := range row { - n := gd.nodes[nodeIndex] + for _, n := range row { n.TopLeft = cursor.Copy() cursor.X += n.Width + HORIZONTAL_PAD rowHeight = math.Max(rowHeight, n.Height) @@ -343,8 +286,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { maxX = math.Max(maxX, rowWidth) // set all nodes in row to the same height - for _, nodeIndex := range row { - n := gd.nodes[nodeIndex] + for _, n := range row { n.Height = rowHeight } @@ -374,8 +316,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { delta := maxX - rowWidth nodes := []*d2graph.Object{} var widest float64 - for _, nodeIndex := range row { - n := gd.nodes[nodeIndex] + for _, n := range row { widest = math.Max(widest, n.Width) nodes = append(nodes, n) } @@ -386,8 +327,8 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { for _, n := range nodes { if n.Width < widest { var index int - for i, nodeIndex := range row { - if n == gd.nodes[nodeIndex] { + for i, node := range row { + if n == node { index = i break } @@ -396,7 +337,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { n.Width += grow // shift following nodes for i := index + 1; i < len(row); i++ { - gd.nodes[row[i]].TopLeft.X += grow + row[i].TopLeft.X += grow } delta -= grow if delta <= 0 { @@ -407,7 +348,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if delta > 0 { grow := delta / float64(len(row)) for i := len(row) - 1; i >= 0; i-- { - n := gd.nodes[row[i]] + n := row[i] n.TopLeft.X += grow * float64(i) n.Width += grow delta -= grow @@ -429,8 +370,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { colHeights := []float64{} for _, column := range layout { colWidth := 0. - for _, nodeIndex := range column { - n := gd.nodes[nodeIndex] + for _, n := range column { n.TopLeft = cursor.Copy() cursor.Y += n.Height + VERTICAL_PAD colWidth = math.Max(colWidth, n.Width) @@ -439,8 +379,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { colHeights = append(colHeights, colHeight) maxY = math.Max(maxY, colHeight) // set all nodes in column to the same width - for _, nodeIndex := range column { - n := gd.nodes[nodeIndex] + for _, n := range column { n.Width = colWidth } @@ -468,8 +407,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { delta := maxY - colHeight nodes := []*d2graph.Object{} var tallest float64 - for _, nodeIndex := range column { - n := gd.nodes[nodeIndex] + for _, n := range column { tallest = math.Max(tallest, n.Height) nodes = append(nodes, n) } @@ -480,8 +418,8 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { for _, n := range nodes { if n.Height < tallest { var index int - for i, nodeIndex := range column { - if n == gd.nodes[nodeIndex] { + for i, node := range column { + if n == node { index = i break } @@ -490,7 +428,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { n.Height += grow // shift following nodes for i := index + 1; i < len(column); i++ { - gd.nodes[column[i]].TopLeft.Y += grow + column[i].TopLeft.Y += grow } delta -= grow if delta <= 0 { @@ -501,7 +439,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if delta > 0 { grow := delta / float64(len(column)) for i := len(column) - 1; i >= 0; i-- { - n := gd.nodes[column[i]] + n := column[i] n.TopLeft.Y += grow * float64(i) n.Height += grow delta -= grow @@ -513,6 +451,98 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { gd.height = maxY } +// generate the best layout of nodes aiming for each row to be the targetSize width +// if columns is true, each column aims to have the targetSize height +func (gd *gridDiagram) getBestLayout(targetSize float64, columns bool) [][]*d2graph.Object { + var nCuts int + if columns { + nCuts = gd.columns - 1 + } else { + nCuts = gd.rows - 1 + } + if nCuts == 0 { + return genLayout(gd.nodes, nil) + } + + // get all options for where to place these cuts, preferring later cuts over earlier cuts + // with 5 nodes and 2 cuts we have these options: + // . A B C │ D │ E <- these cuts would produce: ┌A─┐ ┌B─┐ ┌C─┐ + // . A B │ C D │ E └──┘ └──┘ └──┘ + // . A │ B C D │ E ┌D───────────┐ + // . A B │ C │ D E └────────────┘ + // . A │ B C │ D E ┌E───────────┐ + // . A │ B │ C D E └────────────┘ + divisions := genDivisions(gd.nodes, nCuts) + + var bestLayout [][]*d2graph.Object + bestDist := math.MaxFloat64 + // of these divisions, find the layout with rows closest to the targetSize + for _, division := range divisions { + layout := genLayout(gd.nodes, division) + dist := getDistToTarget(layout, targetSize, columns) + if dist < bestDist { + bestLayout = layout + bestDist = dist + } + } + + return bestLayout +} + +// get all possible divisions of nodes by the number of cuts +func genDivisions(nodes []*d2graph.Object, nCuts int) (divisions [][]int) { + if len(nodes) < 2 || nCuts == 0 { + return nil + } + // we go in this order to prefer extra nodes in starting rows rather than later ones + lastNode := len(nodes) - 1 + for index := lastNode; index >= nCuts; index-- { + if nCuts > 1 { + for _, inner := range genDivisions(nodes[:index], nCuts-1) { + divisions = append(divisions, append(inner, index-1)) + } + } else { + divisions = append(divisions, []int{index - 1}) + } + } + + return divisions +} + +// generate a grid of nodes from the given cut indices +func genLayout(nodes []*d2graph.Object, cutIndices []int) [][]*d2graph.Object { + layout := make([][]*d2graph.Object, len(cutIndices)+1) + nodeIndex := 0 + for i := 0; i <= len(cutIndices); i++ { + var stop int + if i < len(cutIndices) { + stop = cutIndices[i] + } else { + stop = len(nodes) - 1 + } + for ; nodeIndex <= stop; nodeIndex++ { + layout[i] = append(layout[i], nodes[nodeIndex]) + } + } + return layout +} + +func getDistToTarget(layout [][]*d2graph.Object, targetSize float64, columns bool) float64 { + totalDelta := 0. + for _, row := range layout { + rowSize := 0. + for _, n := range row { + if columns { + rowSize += n.Height + VERTICAL_PAD + } else { + rowSize += n.Width + HORIZONTAL_PAD + } + } + totalDelta += math.Abs(rowSize - targetSize) + } + return totalDelta +} + // cleanup restores the graph after the core layout engine finishes // - translating the grid to its position placed by the core layout engine // - restore the children of the grid From 8b3ba86da338044f023917af5885b2b132b25480 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 5 Apr 2023 20:03:07 -0700 Subject: [PATCH 28/31] update test --- .../stable/grid_tests/dagre/board.exp.json | 108 ++++++------ .../stable/grid_tests/dagre/sketch.exp.svg | 160 +++++++++--------- .../stable/grid_tests/elk/board.exp.json | 108 ++++++------ .../stable/grid_tests/elk/sketch.exp.svg | 160 +++++++++--------- 4 files changed, 268 insertions(+), 268 deletions(-) diff --git a/e2etests/testdata/stable/grid_tests/dagre/board.exp.json b/e2etests/testdata/stable/grid_tests/dagre/board.exp.json index a82de5acf..15c3df149 100644 --- a/e2etests/testdata/stable/grid_tests/dagre/board.exp.json +++ b/e2etests/testdata/stable/grid_tests/dagre/board.exp.json @@ -2632,10 +2632,10 @@ "type": "rectangle", "pos": { "x": 3548, - "y": 159 + "y": 212 }, - "width": 267, - "height": 504, + "width": 359, + "height": 398, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -2673,7 +2673,7 @@ "type": "rectangle", "pos": { "x": 3608, - "y": 219 + "y": 272 }, "width": 53, "height": 66, @@ -2714,7 +2714,7 @@ "type": "rectangle", "pos": { "x": 3701, - "y": 219 + "y": 272 }, "width": 53, "height": 66, @@ -2754,8 +2754,8 @@ "id": "rows 3.c", "type": "rectangle", "pos": { - "x": 3608, - "y": 325 + "x": 3794, + "y": 272 }, "width": 53, "height": 66, @@ -2795,10 +2795,10 @@ "id": "rows 3.d", "type": "rectangle", "pos": { - "x": 3701, - "y": 325 + "x": 3608, + "y": 378 }, - "width": 54, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2836,10 +2836,10 @@ "id": "rows 3.e", "type": "rectangle", "pos": { - "x": 3608, - "y": 431 + "x": 3747, + "y": 378 }, - "width": 53, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2877,10 +2877,10 @@ "id": "rows 3.f", "type": "rectangle", "pos": { - "x": 3701, - "y": 431 + "x": 3608, + "y": 484 }, - "width": 53, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2918,10 +2918,10 @@ "id": "rows 3.g", "type": "rectangle", "pos": { - "x": 3608, - "y": 537 + "x": 3747, + "y": 484 }, - "width": 147, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2959,11 +2959,11 @@ "id": "columns 3", "type": "rectangle", "pos": { - "x": 3875, - "y": 265 + "x": 3967, + "y": 212 }, - "width": 454, - "height": 292, + "width": 361, + "height": 398, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3000,8 +3000,8 @@ "id": "columns 3.a", "type": "rectangle", "pos": { - "x": 3935, - "y": 325 + "x": 4027, + "y": 272 }, "width": 53, "height": 66, @@ -3041,8 +3041,8 @@ "id": "columns 3.b", "type": "rectangle", "pos": { - "x": 3935, - "y": 431 + "x": 4027, + "y": 378 }, "width": 53, "height": 66, @@ -3082,10 +3082,10 @@ "id": "columns 3.c", "type": "rectangle", "pos": { - "x": 4028, - "y": 325 + "x": 4027, + "y": 484 }, - "width": 54, + "width": 53, "height": 66, "opacity": 1, "strokeDash": 0, @@ -3123,11 +3123,11 @@ "id": "columns 3.d", "type": "rectangle", "pos": { - "x": 4028, - "y": 431 + "x": 4120, + "y": 272 }, "width": 54, - "height": 66, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3164,11 +3164,11 @@ "id": "columns 3.e", "type": "rectangle", "pos": { - "x": 4122, - "y": 325 + "x": 4120, + "y": 431 }, - "width": 53, - "height": 66, + "width": 54, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3205,11 +3205,11 @@ "id": "columns 3.f", "type": "rectangle", "pos": { - "x": 4122, - "y": 431 + "x": 4214, + "y": 272 }, - "width": 53, - "height": 66, + "width": 54, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3246,11 +3246,11 @@ "id": "columns 3.g", "type": "rectangle", "pos": { - "x": 4215, - "y": 325 + "x": 4214, + "y": 431 }, "width": 54, - "height": 172, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3287,7 +3287,7 @@ "id": "widths heights", "type": "rectangle", "pos": { - "x": 4389, + "x": 4388, "y": 28 }, "width": 886, @@ -3328,7 +3328,7 @@ "id": "widths heights.a w200", "type": "rectangle", "pos": { - "x": 4449, + "x": 4448, "y": 88 }, "width": 200, @@ -3369,7 +3369,7 @@ "id": "widths heights.b h300", "type": "rectangle", "pos": { - "x": 4689, + "x": 4688, "y": 88 }, "width": 86, @@ -3410,7 +3410,7 @@ "id": "widths heights.c", "type": "rectangle", "pos": { - "x": 4815, + "x": 4814, "y": 88 }, "width": 400, @@ -3451,7 +3451,7 @@ "id": "widths heights.d h200", "type": "rectangle", "pos": { - "x": 4449, + "x": 4448, "y": 428 }, "width": 200, @@ -3492,7 +3492,7 @@ "id": "widths heights.e", "type": "rectangle", "pos": { - "x": 4689, + "x": 4688, "y": 428 }, "width": 86, @@ -3533,7 +3533,7 @@ "id": "widths heights.f w400", "type": "rectangle", "pos": { - "x": 4815, + "x": 4814, "y": 428 }, "width": 400, @@ -3574,7 +3574,7 @@ "id": "widths heights.g", "type": "rectangle", "pos": { - "x": 4449, + "x": 4448, "y": 668 }, "width": 200, @@ -3615,7 +3615,7 @@ "id": "widths heights.h", "type": "rectangle", "pos": { - "x": 4689, + "x": 4688, "y": 668 }, "width": 86, @@ -3656,7 +3656,7 @@ "id": "widths heights.i", "type": "rectangle", "pos": { - "x": 4815, + "x": 4814, "y": 668 }, "width": 400, diff --git a/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg b/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg index 43be0cd45..4f6c4484f 100644 --- a/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/grid_tests/dagre/sketch.exp.svg @@ -1,16 +1,16 @@ -rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3widths heightsabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga w200b h300cd h200ef w400ghi - + .d2-161667186 .fill-N1{fill:#0A0F25;} + .d2-161667186 .fill-N2{fill:#676C7E;} + .d2-161667186 .fill-N3{fill:#9499AB;} + .d2-161667186 .fill-N4{fill:#CFD2DD;} + .d2-161667186 .fill-N5{fill:#DEE1EB;} + .d2-161667186 .fill-N6{fill:#EEF1F8;} + .d2-161667186 .fill-N7{fill:#FFFFFF;} + .d2-161667186 .fill-B1{fill:#0D32B2;} + .d2-161667186 .fill-B2{fill:#0D32B2;} + .d2-161667186 .fill-B3{fill:#E3E9FD;} + .d2-161667186 .fill-B4{fill:#E3E9FD;} + .d2-161667186 .fill-B5{fill:#EDF0FD;} + .d2-161667186 .fill-B6{fill:#F7F8FE;} + .d2-161667186 .fill-AA2{fill:#4A6FF3;} + .d2-161667186 .fill-AA4{fill:#EDF0FD;} + .d2-161667186 .fill-AA5{fill:#F7F8FE;} + .d2-161667186 .fill-AB4{fill:#EDF0FD;} + .d2-161667186 .fill-AB5{fill:#F7F8FE;} + .d2-161667186 .stroke-N1{stroke:#0A0F25;} + .d2-161667186 .stroke-N2{stroke:#676C7E;} + .d2-161667186 .stroke-N3{stroke:#9499AB;} + .d2-161667186 .stroke-N4{stroke:#CFD2DD;} + .d2-161667186 .stroke-N5{stroke:#DEE1EB;} + .d2-161667186 .stroke-N6{stroke:#EEF1F8;} + .d2-161667186 .stroke-N7{stroke:#FFFFFF;} + .d2-161667186 .stroke-B1{stroke:#0D32B2;} + .d2-161667186 .stroke-B2{stroke:#0D32B2;} + .d2-161667186 .stroke-B3{stroke:#E3E9FD;} + .d2-161667186 .stroke-B4{stroke:#E3E9FD;} + .d2-161667186 .stroke-B5{stroke:#EDF0FD;} + .d2-161667186 .stroke-B6{stroke:#F7F8FE;} + .d2-161667186 .stroke-AA2{stroke:#4A6FF3;} + .d2-161667186 .stroke-AA4{stroke:#EDF0FD;} + .d2-161667186 .stroke-AA5{stroke:#F7F8FE;} + .d2-161667186 .stroke-AB4{stroke:#EDF0FD;} + .d2-161667186 .stroke-AB5{stroke:#F7F8FE;} + .d2-161667186 .background-color-N1{background-color:#0A0F25;} + .d2-161667186 .background-color-N2{background-color:#676C7E;} + .d2-161667186 .background-color-N3{background-color:#9499AB;} + .d2-161667186 .background-color-N4{background-color:#CFD2DD;} + .d2-161667186 .background-color-N5{background-color:#DEE1EB;} + .d2-161667186 .background-color-N6{background-color:#EEF1F8;} + .d2-161667186 .background-color-N7{background-color:#FFFFFF;} + .d2-161667186 .background-color-B1{background-color:#0D32B2;} + .d2-161667186 .background-color-B2{background-color:#0D32B2;} + .d2-161667186 .background-color-B3{background-color:#E3E9FD;} + .d2-161667186 .background-color-B4{background-color:#E3E9FD;} + .d2-161667186 .background-color-B5{background-color:#EDF0FD;} + .d2-161667186 .background-color-B6{background-color:#F7F8FE;} + .d2-161667186 .background-color-AA2{background-color:#4A6FF3;} + .d2-161667186 .background-color-AA4{background-color:#EDF0FD;} + .d2-161667186 .background-color-AA5{background-color:#F7F8FE;} + .d2-161667186 .background-color-AB4{background-color:#EDF0FD;} + .d2-161667186 .background-color-AB5{background-color:#F7F8FE;} + .d2-161667186 .color-N1{color:#0A0F25;} + .d2-161667186 .color-N2{color:#676C7E;} + .d2-161667186 .color-N3{color:#9499AB;} + .d2-161667186 .color-N4{color:#CFD2DD;} + .d2-161667186 .color-N5{color:#DEE1EB;} + .d2-161667186 .color-N6{color:#EEF1F8;} + .d2-161667186 .color-N7{color:#FFFFFF;} + .d2-161667186 .color-B1{color:#0D32B2;} + .d2-161667186 .color-B2{color:#0D32B2;} + .d2-161667186 .color-B3{color:#E3E9FD;} + .d2-161667186 .color-B4{color:#E3E9FD;} + .d2-161667186 .color-B5{color:#EDF0FD;} + .d2-161667186 .color-B6{color:#F7F8FE;} + .d2-161667186 .color-AA2{color:#4A6FF3;} + .d2-161667186 .color-AA4{color:#EDF0FD;} + .d2-161667186 .color-AA5{color:#F7F8FE;} + .d2-161667186 .color-AB4{color:#EDF0FD;} + .d2-161667186 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3widths heightsabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga w200b h300cd h200ef w400ghi + \ No newline at end of file diff --git a/e2etests/testdata/stable/grid_tests/elk/board.exp.json b/e2etests/testdata/stable/grid_tests/elk/board.exp.json index bb7e1930e..95b4c1c12 100644 --- a/e2etests/testdata/stable/grid_tests/elk/board.exp.json +++ b/e2etests/testdata/stable/grid_tests/elk/board.exp.json @@ -2632,10 +2632,10 @@ "type": "rectangle", "pos": { "x": 3240, - "y": 171 + "y": 224 }, - "width": 267, - "height": 504, + "width": 359, + "height": 398, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -2673,7 +2673,7 @@ "type": "rectangle", "pos": { "x": 3300, - "y": 231 + "y": 284 }, "width": 53, "height": 66, @@ -2714,7 +2714,7 @@ "type": "rectangle", "pos": { "x": 3393, - "y": 231 + "y": 284 }, "width": 53, "height": 66, @@ -2754,8 +2754,8 @@ "id": "rows 3.c", "type": "rectangle", "pos": { - "x": 3300, - "y": 337 + "x": 3486, + "y": 284 }, "width": 53, "height": 66, @@ -2795,10 +2795,10 @@ "id": "rows 3.d", "type": "rectangle", "pos": { - "x": 3393, - "y": 337 + "x": 3300, + "y": 390 }, - "width": 54, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2836,10 +2836,10 @@ "id": "rows 3.e", "type": "rectangle", "pos": { - "x": 3300, - "y": 443 + "x": 3439, + "y": 390 }, - "width": 53, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2877,10 +2877,10 @@ "id": "rows 3.f", "type": "rectangle", "pos": { - "x": 3393, - "y": 443 + "x": 3300, + "y": 496 }, - "width": 53, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2918,10 +2918,10 @@ "id": "rows 3.g", "type": "rectangle", "pos": { - "x": 3300, - "y": 549 + "x": 3439, + "y": 496 }, - "width": 147, + "width": 99, "height": 66, "opacity": 1, "strokeDash": 0, @@ -2959,11 +2959,11 @@ "id": "columns 3", "type": "rectangle", "pos": { - "x": 3527, - "y": 277 + "x": 3619, + "y": 224 }, - "width": 454, - "height": 292, + "width": 361, + "height": 398, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3000,8 +3000,8 @@ "id": "columns 3.a", "type": "rectangle", "pos": { - "x": 3587, - "y": 337 + "x": 3679, + "y": 284 }, "width": 53, "height": 66, @@ -3041,8 +3041,8 @@ "id": "columns 3.b", "type": "rectangle", "pos": { - "x": 3587, - "y": 443 + "x": 3679, + "y": 390 }, "width": 53, "height": 66, @@ -3082,10 +3082,10 @@ "id": "columns 3.c", "type": "rectangle", "pos": { - "x": 3680, - "y": 337 + "x": 3679, + "y": 496 }, - "width": 54, + "width": 53, "height": 66, "opacity": 1, "strokeDash": 0, @@ -3123,11 +3123,11 @@ "id": "columns 3.d", "type": "rectangle", "pos": { - "x": 3680, - "y": 443 + "x": 3772, + "y": 284 }, "width": 54, - "height": 66, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3164,11 +3164,11 @@ "id": "columns 3.e", "type": "rectangle", "pos": { - "x": 3774, - "y": 337 + "x": 3772, + "y": 443 }, - "width": 53, - "height": 66, + "width": 54, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3205,11 +3205,11 @@ "id": "columns 3.f", "type": "rectangle", "pos": { - "x": 3774, - "y": 443 + "x": 3866, + "y": 284 }, - "width": 53, - "height": 66, + "width": 54, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3246,11 +3246,11 @@ "id": "columns 3.g", "type": "rectangle", "pos": { - "x": 3867, - "y": 337 + "x": 3866, + "y": 443 }, "width": 54, - "height": 172, + "height": 119, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -3287,7 +3287,7 @@ "id": "widths heights", "type": "rectangle", "pos": { - "x": 4001, + "x": 4000, "y": 40 }, "width": 886, @@ -3328,7 +3328,7 @@ "id": "widths heights.a w200", "type": "rectangle", "pos": { - "x": 4061, + "x": 4060, "y": 100 }, "width": 200, @@ -3369,7 +3369,7 @@ "id": "widths heights.b h300", "type": "rectangle", "pos": { - "x": 4301, + "x": 4300, "y": 100 }, "width": 86, @@ -3410,7 +3410,7 @@ "id": "widths heights.c", "type": "rectangle", "pos": { - "x": 4427, + "x": 4426, "y": 100 }, "width": 400, @@ -3451,7 +3451,7 @@ "id": "widths heights.d h200", "type": "rectangle", "pos": { - "x": 4061, + "x": 4060, "y": 440 }, "width": 200, @@ -3492,7 +3492,7 @@ "id": "widths heights.e", "type": "rectangle", "pos": { - "x": 4301, + "x": 4300, "y": 440 }, "width": 86, @@ -3533,7 +3533,7 @@ "id": "widths heights.f w400", "type": "rectangle", "pos": { - "x": 4427, + "x": 4426, "y": 440 }, "width": 400, @@ -3574,7 +3574,7 @@ "id": "widths heights.g", "type": "rectangle", "pos": { - "x": 4061, + "x": 4060, "y": 680 }, "width": 200, @@ -3615,7 +3615,7 @@ "id": "widths heights.h", "type": "rectangle", "pos": { - "x": 4301, + "x": 4300, "y": 680 }, "width": 86, @@ -3656,7 +3656,7 @@ "id": "widths heights.i", "type": "rectangle", "pos": { - "x": 4427, + "x": 4426, "y": 680 }, "width": 400, diff --git a/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg b/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg index bfcf25d48..f85853334 100644 --- a/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/grid_tests/elk/sketch.exp.svg @@ -1,16 +1,16 @@ -rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3widths heightsabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga w200b h300cd h200ef w400ghi - + .d2-1021052366 .fill-N1{fill:#0A0F25;} + .d2-1021052366 .fill-N2{fill:#676C7E;} + .d2-1021052366 .fill-N3{fill:#9499AB;} + .d2-1021052366 .fill-N4{fill:#CFD2DD;} + .d2-1021052366 .fill-N5{fill:#DEE1EB;} + .d2-1021052366 .fill-N6{fill:#EEF1F8;} + .d2-1021052366 .fill-N7{fill:#FFFFFF;} + .d2-1021052366 .fill-B1{fill:#0D32B2;} + .d2-1021052366 .fill-B2{fill:#0D32B2;} + .d2-1021052366 .fill-B3{fill:#E3E9FD;} + .d2-1021052366 .fill-B4{fill:#E3E9FD;} + .d2-1021052366 .fill-B5{fill:#EDF0FD;} + .d2-1021052366 .fill-B6{fill:#F7F8FE;} + .d2-1021052366 .fill-AA2{fill:#4A6FF3;} + .d2-1021052366 .fill-AA4{fill:#EDF0FD;} + .d2-1021052366 .fill-AA5{fill:#F7F8FE;} + .d2-1021052366 .fill-AB4{fill:#EDF0FD;} + .d2-1021052366 .fill-AB5{fill:#F7F8FE;} + .d2-1021052366 .stroke-N1{stroke:#0A0F25;} + .d2-1021052366 .stroke-N2{stroke:#676C7E;} + .d2-1021052366 .stroke-N3{stroke:#9499AB;} + .d2-1021052366 .stroke-N4{stroke:#CFD2DD;} + .d2-1021052366 .stroke-N5{stroke:#DEE1EB;} + .d2-1021052366 .stroke-N6{stroke:#EEF1F8;} + .d2-1021052366 .stroke-N7{stroke:#FFFFFF;} + .d2-1021052366 .stroke-B1{stroke:#0D32B2;} + .d2-1021052366 .stroke-B2{stroke:#0D32B2;} + .d2-1021052366 .stroke-B3{stroke:#E3E9FD;} + .d2-1021052366 .stroke-B4{stroke:#E3E9FD;} + .d2-1021052366 .stroke-B5{stroke:#EDF0FD;} + .d2-1021052366 .stroke-B6{stroke:#F7F8FE;} + .d2-1021052366 .stroke-AA2{stroke:#4A6FF3;} + .d2-1021052366 .stroke-AA4{stroke:#EDF0FD;} + .d2-1021052366 .stroke-AA5{stroke:#F7F8FE;} + .d2-1021052366 .stroke-AB4{stroke:#EDF0FD;} + .d2-1021052366 .stroke-AB5{stroke:#F7F8FE;} + .d2-1021052366 .background-color-N1{background-color:#0A0F25;} + .d2-1021052366 .background-color-N2{background-color:#676C7E;} + .d2-1021052366 .background-color-N3{background-color:#9499AB;} + .d2-1021052366 .background-color-N4{background-color:#CFD2DD;} + .d2-1021052366 .background-color-N5{background-color:#DEE1EB;} + .d2-1021052366 .background-color-N6{background-color:#EEF1F8;} + .d2-1021052366 .background-color-N7{background-color:#FFFFFF;} + .d2-1021052366 .background-color-B1{background-color:#0D32B2;} + .d2-1021052366 .background-color-B2{background-color:#0D32B2;} + .d2-1021052366 .background-color-B3{background-color:#E3E9FD;} + .d2-1021052366 .background-color-B4{background-color:#E3E9FD;} + .d2-1021052366 .background-color-B5{background-color:#EDF0FD;} + .d2-1021052366 .background-color-B6{background-color:#F7F8FE;} + .d2-1021052366 .background-color-AA2{background-color:#4A6FF3;} + .d2-1021052366 .background-color-AA4{background-color:#EDF0FD;} + .d2-1021052366 .background-color-AA5{background-color:#F7F8FE;} + .d2-1021052366 .background-color-AB4{background-color:#EDF0FD;} + .d2-1021052366 .background-color-AB5{background-color:#F7F8FE;} + .d2-1021052366 .color-N1{color:#0A0F25;} + .d2-1021052366 .color-N2{color:#676C7E;} + .d2-1021052366 .color-N3{color:#9499AB;} + .d2-1021052366 .color-N4{color:#CFD2DD;} + .d2-1021052366 .color-N5{color:#DEE1EB;} + .d2-1021052366 .color-N6{color:#EEF1F8;} + .d2-1021052366 .color-N7{color:#FFFFFF;} + .d2-1021052366 .color-B1{color:#0D32B2;} + .d2-1021052366 .color-B2{color:#0D32B2;} + .d2-1021052366 .color-B3{color:#E3E9FD;} + .d2-1021052366 .color-B4{color:#E3E9FD;} + .d2-1021052366 .color-B5{color:#EDF0FD;} + .d2-1021052366 .color-B6{color:#F7F8FE;} + .d2-1021052366 .color-AA2{color:#4A6FF3;} + .d2-1021052366 .color-AA4{color:#EDF0FD;} + .d2-1021052366 .color-AA5{color:#F7F8FE;} + .d2-1021052366 .color-AB4{color:#EDF0FD;} + .d2-1021052366 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>rows 1columns 1rows 2columns 2rows 2 columns 2columns 2 rows 2rows 3 columns 3columns 3 rows 3rows 3columns 3widths heightsabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga w200b h300cd h200ef w400ghi + \ No newline at end of file From bab54b4030ba90f23fb339cd126305b651b71b38 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Thu, 6 Apr 2023 14:30:45 -0700 Subject: [PATCH 29/31] cleanup --- d2layouts/d2grid/grid_diagram.go | 45 +++--- d2layouts/d2grid/layout.go | 230 +++++++++++++++---------------- 2 files changed, 140 insertions(+), 135 deletions(-) diff --git a/d2layouts/d2grid/grid_diagram.go b/d2layouts/d2grid/grid_diagram.go index c26a6e917..6b4d8dfb3 100644 --- a/d2layouts/d2grid/grid_diagram.go +++ b/d2layouts/d2grid/grid_diagram.go @@ -8,18 +8,20 @@ import ( type gridDiagram struct { root *d2graph.Object - nodes []*d2graph.Object + objects []*d2graph.Object rows int columns int - rowDominant bool + // if true, place objects left to right along rows + // if false, place objects top to bottom along columns + rowDirected bool width float64 height float64 } func newGridDiagram(root *d2graph.Object) *gridDiagram { - gd := gridDiagram{root: root, nodes: root.ChildrenArray} + gd := gridDiagram{root: root, objects: root.ChildrenArray} if root.Attributes.Rows != nil { gd.rows, _ = strconv.Atoi(root.Attributes.Rows.Value) } @@ -27,30 +29,31 @@ func newGridDiagram(root *d2graph.Object) *gridDiagram { gd.columns, _ = strconv.Atoi(root.Attributes.Columns.Value) } - // compute exact row/column count based on values entered - if gd.columns == 0 { - gd.rowDominant = true - } else if gd.rows == 0 { - gd.rowDominant = false - } else { - // if keyword rows is first, rows are primary, columns secondary. + if gd.rows != 0 && gd.columns != 0 { + // . row-directed column-directed + // . ┌───────┐ ┌───────┐ + // . │ a b c │ │ a d g │ + // . │ d e f │ │ b e h │ + // . │ g h i │ │ c f i │ + // . └───────┘ └───────┘ + // if keyword rows is first, make it row-directed, if columns is first it is column-directed if root.Attributes.Rows.MapKey.Range.Before(root.Attributes.Columns.MapKey.Range) { - gd.rowDominant = true + gd.rowDirected = true } - // rows and columns specified, but we want to continue naturally if user enters more nodes - // e.g. 2 rows, 3 columns specified + g node added: │ with 3 columns, 2 rows: + // rows and columns specified, but we want to continue naturally if user enters more objects + // e.g. 2 rows, 3 columns specified + g added: │ with 3 columns, 2 rows: // . original add row add column │ original add row add column // . ┌───────┐ ┌───────┐ ┌─────────┐ │ ┌───────┐ ┌───────┐ ┌─────────┐ // . │ a b c │ │ a b c │ │ a b c d │ │ │ a c e │ │ a d g │ │ a c e g │ // . │ d e f │ │ d e f │ │ e f g │ │ │ b d f │ │ b e │ │ b d f │ // . └───────┘ │ g │ └─────────┘ │ └───────┘ │ c f │ └─────────┘ // . └───────┘ ▲ │ └───────┘ ▲ - // . ▲ └─existing nodes modified │ ▲ └─existing nodes preserved - // . └─existing rows preserved │ └─existing rows modified + // . ▲ └─existing objects modified│ ▲ └─existing columns preserved + // . └─existing rows preserved │ └─existing objects modified capacity := gd.rows * gd.columns - for capacity < len(gd.nodes) { - if gd.rowDominant { + for capacity < len(gd.objects) { + if gd.rowDirected { gd.rows++ capacity += gd.columns } else { @@ -58,13 +61,15 @@ func newGridDiagram(root *d2graph.Object) *gridDiagram { capacity += gd.rows } } + } else if gd.columns == 0 { + gd.rowDirected = true } return &gd } func (gd *gridDiagram) shift(dx, dy float64) { - for _, obj := range gd.nodes { + for _, obj := range gd.objects { obj.TopLeft.X += dx obj.TopLeft.Y += dy } @@ -73,9 +78,9 @@ func (gd *gridDiagram) shift(dx, dy float64) { func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) { obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = make([]*d2graph.Object, 0) - for _, child := range gd.nodes { + for _, child := range gd.objects { obj.Children[child.ID] = child obj.ChildrenArray = append(obj.ChildrenArray, child) } - graph.Objects = append(graph.Objects, gd.nodes...) + graph.Objects = append(graph.Objects, gd.objects...) } diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index bdfab8f98..1edae9066 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -94,8 +94,8 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph) (gridDiagrams ma obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) gridDiagrams[obj.AbsID()] = gd - for _, node := range gd.nodes { - toRemove[node] = struct{}{} + for _, o := range gd.objects { + toRemove[o] = struct{}{} } } } @@ -123,12 +123,12 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) { } // position labels and icons - for _, n := range gd.nodes { - if n.Attributes.Icon != nil { - n.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) - n.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) + for _, o := range gd.objects { + if o.Attributes.Icon != nil { + o.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) + o.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) } else { - n.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) + o.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } } @@ -136,19 +136,19 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) { } func (gd *gridDiagram) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { - // layout nodes in a grid with these 2 properties: - // all nodes in the same row should have the same height - // all nodes in the same column should have the same width + // layout objects in a grid with these 2 properties: + // all objects in the same row should have the same height + // all objects in the same column should have the same width - getNode := func(rowIndex, columnIndex int) *d2graph.Object { + getObject := func(rowIndex, columnIndex int) *d2graph.Object { var index int - if gd.rowDominant { + if gd.rowDirected { index = rowIndex*gd.columns + columnIndex } else { index = columnIndex*gd.rows + rowIndex } - if index < len(gd.nodes) { - return gd.nodes[index] + if index < len(gd.objects) { + return gd.objects[index] } return nil } @@ -158,38 +158,38 @@ func (gd *gridDiagram) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { for i := 0; i < gd.rows; i++ { rowHeight := 0. for j := 0; j < gd.columns; j++ { - n := getNode(i, j) - if n == nil { + o := getObject(i, j) + if o == nil { break } - rowHeight = math.Max(rowHeight, n.Height) + rowHeight = math.Max(rowHeight, o.Height) } rowHeights = append(rowHeights, rowHeight) } for j := 0; j < gd.columns; j++ { columnWidth := 0. for i := 0; i < gd.rows; i++ { - n := getNode(i, j) - if n == nil { + o := getObject(i, j) + if o == nil { break } - columnWidth = math.Max(columnWidth, n.Width) + columnWidth = math.Max(columnWidth, o.Width) } colWidths = append(colWidths, columnWidth) } cursor := geo.NewPoint(0, 0) - if gd.rowDominant { + if gd.rowDirected { for i := 0; i < gd.rows; i++ { for j := 0; j < gd.columns; j++ { - n := getNode(i, j) - if n == nil { + o := getObject(i, j) + if o == nil { break } - n.Width = colWidths[j] - n.Height = rowHeights[i] - n.TopLeft = cursor.Copy() - cursor.X += n.Width + HORIZONTAL_PAD + o.Width = colWidths[j] + o.Height = rowHeights[i] + o.TopLeft = cursor.Copy() + cursor.X += o.Width + HORIZONTAL_PAD } cursor.X = 0 cursor.Y += rowHeights[i] + VERTICAL_PAD @@ -197,14 +197,14 @@ func (gd *gridDiagram) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { } else { for j := 0; j < gd.columns; j++ { for i := 0; i < gd.rows; i++ { - n := getNode(i, j) - if n == nil { + o := getObject(i, j) + if o == nil { break } - n.Width = colWidths[j] - n.Height = rowHeights[i] - n.TopLeft = cursor.Copy() - cursor.Y += n.Height + VERTICAL_PAD + o.Width = colWidths[j] + o.Height = rowHeights[i] + o.TopLeft = cursor.Copy() + cursor.Y += o.Height + VERTICAL_PAD } cursor.X += colWidths[j] + HORIZONTAL_PAD cursor.Y = 0 @@ -225,14 +225,14 @@ func (gd *gridDiagram) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) { } func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { - // assume we have the following nodes to layout: + // assume we have the following objects to layout: // . ┌A──────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐ // . └───────────────┘ │ │ │ │ │ │ │ │ // . │ │ └──────────┘ │ │ │ │ // . │ │ │ │ └─────────────────┘ // . └───┘ │ │ // . └─────────┘ - // Note: if the grid is row dominant, all nodes should be the same height (same width if column dominant) + // Note: if the grid is row dominant, all objects should be the same height (same width if column dominant) // . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐ // . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │ │ │ │ // . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │ │ │ │ @@ -242,15 +242,15 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { // we want to split up the total width across the N rows or columns as evenly as possible var totalWidth, totalHeight float64 - for _, n := range gd.nodes { - totalWidth += n.Width - totalHeight += n.Height + for _, o := range gd.objects { + totalWidth += o.Width + totalHeight += o.Height } - totalWidth += HORIZONTAL_PAD * float64(len(gd.nodes)-gd.rows) - totalHeight += VERTICAL_PAD * float64(len(gd.nodes)-gd.columns) + totalWidth += HORIZONTAL_PAD * float64(len(gd.objects)-gd.rows) + totalHeight += VERTICAL_PAD * float64(len(gd.objects)-gd.columns) var layout [][]*d2graph.Object - if gd.rowDominant { + if gd.rowDirected { targetWidth := totalWidth / float64(gd.rows) layout = gd.getBestLayout(targetWidth, false) } else { @@ -260,8 +260,8 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { cursor := geo.NewPoint(0, 0) var maxY, maxX float64 - if gd.rowDominant { - // if we have 2 rows, then each row's nodes should have the same height + if gd.rowDirected { + // if we have 2 rows, then each row's objects should have the same height // . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C) // . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │ // . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │ @@ -276,18 +276,18 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { rowWidths := []float64{} for _, row := range layout { rowHeight := 0. - for _, n := range row { - n.TopLeft = cursor.Copy() - cursor.X += n.Width + HORIZONTAL_PAD - rowHeight = math.Max(rowHeight, n.Height) + for _, o := range row { + o.TopLeft = cursor.Copy() + cursor.X += o.Width + HORIZONTAL_PAD + rowHeight = math.Max(rowHeight, o.Height) } rowWidth := cursor.X - HORIZONTAL_PAD rowWidths = append(rowWidths, rowWidth) maxX = math.Max(maxX, rowWidth) - // set all nodes in row to the same height - for _, n := range row { - n.Height = rowHeight + // set all objects in row to the same height + for _, o := range row { + o.Height = rowHeight } // new row @@ -296,7 +296,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { } maxY = cursor.Y - VERTICAL_PAD - // then expand thinnest nodes to make each row the same width + // then expand thinnest objects to make each row the same width // . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C) // . │ │ │ │ │ │ │ // . │ │ │ │ │ │ │ @@ -314,28 +314,28 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { continue } delta := maxX - rowWidth - nodes := []*d2graph.Object{} + objects := []*d2graph.Object{} var widest float64 - for _, n := range row { - widest = math.Max(widest, n.Width) - nodes = append(nodes, n) + for _, o := range row { + widest = math.Max(widest, o.Width) + objects = append(objects, o) } - sort.Slice(nodes, func(i, j int) bool { - return nodes[i].Width < nodes[j].Width + sort.Slice(objects, func(i, j int) bool { + return objects[i].Width < objects[j].Width }) - // expand smaller nodes to fill remaining space - for _, n := range nodes { - if n.Width < widest { + // expand smaller objects to fill remaining space + for _, o := range objects { + if o.Width < widest { var index int - for i, node := range row { - if n == node { + for i, rowObj := range row { + if o == rowObj { index = i break } } - grow := math.Min(widest-n.Width, delta) - n.Width += grow - // shift following nodes + grow := math.Min(widest-o.Width, delta) + o.Width += grow + // shift following objects for i := index + 1; i < len(row); i++ { row[i].TopLeft.X += grow } @@ -348,15 +348,15 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if delta > 0 { grow := delta / float64(len(row)) for i := len(row) - 1; i >= 0; i-- { - n := row[i] - n.TopLeft.X += grow * float64(i) - n.Width += grow + o := row[i] + o.TopLeft.X += grow * float64(i) + o.Width += grow delta -= grow } } } } else { - // if we have 3 columns, then each column's nodes should have the same width + // if we have 3 columns, then each column's objects should have the same width // . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤ // . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐ // . └──────────────┘ │ │ │ │ @@ -370,17 +370,17 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { colHeights := []float64{} for _, column := range layout { colWidth := 0. - for _, n := range column { - n.TopLeft = cursor.Copy() - cursor.Y += n.Height + VERTICAL_PAD - colWidth = math.Max(colWidth, n.Width) + for _, o := range column { + o.TopLeft = cursor.Copy() + cursor.Y += o.Height + VERTICAL_PAD + colWidth = math.Max(colWidth, o.Width) } colHeight := cursor.Y - VERTICAL_PAD colHeights = append(colHeights, colHeight) maxY = math.Max(maxY, colHeight) - // set all nodes in column to the same width - for _, n := range column { - n.Width = colWidth + // set all objects in column to the same width + for _, o := range column { + o.Width = colWidth } // new column @@ -388,7 +388,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { cursor.X += colWidth + HORIZONTAL_PAD } maxX = cursor.X - HORIZONTAL_PAD - // then expand shortest nodes to make each column the same height + // then expand shortest objects to make each column the same height // . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤ // . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐ // . ├ ─ ─ ─ ─ ─ ─ ┤ │ │ │ │ @@ -405,28 +405,28 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { continue } delta := maxY - colHeight - nodes := []*d2graph.Object{} + objects := []*d2graph.Object{} var tallest float64 - for _, n := range column { - tallest = math.Max(tallest, n.Height) - nodes = append(nodes, n) + for _, o := range column { + tallest = math.Max(tallest, o.Height) + objects = append(objects, o) } - sort.Slice(nodes, func(i, j int) bool { - return nodes[i].Height < nodes[j].Height + sort.Slice(objects, func(i, j int) bool { + return objects[i].Height < objects[j].Height }) - // expand smaller nodes to fill remaining space - for _, n := range nodes { - if n.Height < tallest { + // expand smaller objects to fill remaining space + for _, o := range objects { + if o.Height < tallest { var index int - for i, node := range column { - if n == node { + for i, colObj := range column { + if o == colObj { index = i break } } - grow := math.Min(tallest-n.Height, delta) - n.Height += grow - // shift following nodes + grow := math.Min(tallest-o.Height, delta) + o.Height += grow + // shift following objects for i := index + 1; i < len(column); i++ { column[i].TopLeft.Y += grow } @@ -439,9 +439,9 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { if delta > 0 { grow := delta / float64(len(column)) for i := len(column) - 1; i >= 0; i-- { - n := column[i] - n.TopLeft.Y += grow * float64(i) - n.Height += grow + o := column[i] + o.TopLeft.Y += grow * float64(i) + o.Height += grow delta -= grow } } @@ -451,7 +451,7 @@ func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) { gd.height = maxY } -// generate the best layout of nodes aiming for each row to be the targetSize width +// generate the best layout of objects aiming for each row to be the targetSize width // if columns is true, each column aims to have the targetSize height func (gd *gridDiagram) getBestLayout(targetSize float64, columns bool) [][]*d2graph.Object { var nCuts int @@ -461,24 +461,24 @@ func (gd *gridDiagram) getBestLayout(targetSize float64, columns bool) [][]*d2gr nCuts = gd.rows - 1 } if nCuts == 0 { - return genLayout(gd.nodes, nil) + return genLayout(gd.objects, nil) } // get all options for where to place these cuts, preferring later cuts over earlier cuts - // with 5 nodes and 2 cuts we have these options: + // with 5 objects and 2 cuts we have these options: // . A B C │ D │ E <- these cuts would produce: ┌A─┐ ┌B─┐ ┌C─┐ // . A B │ C D │ E └──┘ └──┘ └──┘ // . A │ B C D │ E ┌D───────────┐ // . A B │ C │ D E └────────────┘ // . A │ B C │ D E ┌E───────────┐ // . A │ B │ C D E └────────────┘ - divisions := genDivisions(gd.nodes, nCuts) + divisions := genDivisions(gd.objects, nCuts) var bestLayout [][]*d2graph.Object bestDist := math.MaxFloat64 // of these divisions, find the layout with rows closest to the targetSize for _, division := range divisions { - layout := genLayout(gd.nodes, division) + layout := genLayout(gd.objects, division) dist := getDistToTarget(layout, targetSize, columns) if dist < bestDist { bestLayout = layout @@ -489,16 +489,16 @@ func (gd *gridDiagram) getBestLayout(targetSize float64, columns bool) [][]*d2gr return bestLayout } -// get all possible divisions of nodes by the number of cuts -func genDivisions(nodes []*d2graph.Object, nCuts int) (divisions [][]int) { - if len(nodes) < 2 || nCuts == 0 { +// get all possible divisions of objects by the number of cuts +func genDivisions(objects []*d2graph.Object, nCuts int) (divisions [][]int) { + if len(objects) < 2 || nCuts == 0 { return nil } - // we go in this order to prefer extra nodes in starting rows rather than later ones - lastNode := len(nodes) - 1 - for index := lastNode; index >= nCuts; index-- { + // we go in this order to prefer extra objects in starting rows rather than later ones + lastObj := len(objects) - 1 + for index := lastObj; index >= nCuts; index-- { if nCuts > 1 { - for _, inner := range genDivisions(nodes[:index], nCuts-1) { + for _, inner := range genDivisions(objects[:index], nCuts-1) { divisions = append(divisions, append(inner, index-1)) } } else { @@ -509,19 +509,19 @@ func genDivisions(nodes []*d2graph.Object, nCuts int) (divisions [][]int) { return divisions } -// generate a grid of nodes from the given cut indices -func genLayout(nodes []*d2graph.Object, cutIndices []int) [][]*d2graph.Object { +// generate a grid of objects from the given cut indices +func genLayout(objects []*d2graph.Object, cutIndices []int) [][]*d2graph.Object { layout := make([][]*d2graph.Object, len(cutIndices)+1) - nodeIndex := 0 + objIndex := 0 for i := 0; i <= len(cutIndices); i++ { var stop int if i < len(cutIndices) { stop = cutIndices[i] } else { - stop = len(nodes) - 1 + stop = len(objects) - 1 } - for ; nodeIndex <= stop; nodeIndex++ { - layout[i] = append(layout[i], nodes[nodeIndex]) + for ; objIndex <= stop; objIndex++ { + layout[i] = append(layout[i], objects[objIndex]) } } return layout @@ -531,11 +531,11 @@ func getDistToTarget(layout [][]*d2graph.Object, targetSize float64, columns boo totalDelta := 0. for _, row := range layout { rowSize := 0. - for _, n := range row { + for _, o := range row { if columns { - rowSize += n.Height + VERTICAL_PAD + rowSize += o.Height + VERTICAL_PAD } else { - rowSize += n.Width + HORIZONTAL_PAD + rowSize += o.Width + HORIZONTAL_PAD } } totalDelta += math.Abs(rowSize - targetSize) From 37fc3ea8e0e8336a864f2c248f3e3d64af4467d3 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Thu, 6 Apr 2023 15:32:09 -0700 Subject: [PATCH 30/31] cleanup --- d2compiler/compile.go | 11 ++++++----- d2compiler/compile_test.go | 10 +++++----- d2graph/grid_diagram.go | 6 +++--- d2layouts/d2grid/grid_diagram.go | 3 ++- d2layouts/d2near/layout.go | 2 +- d2layouts/d2sequence/layout.go | 4 ++-- testdata/d2compiler/TestCompile/grid_edge.exp.json | 6 +++--- testdata/d2compiler/TestCompile/grid_nested.exp.json | 4 ++-- 8 files changed, 24 insertions(+), 22 deletions(-) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index c1a252440..07d450257 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -708,7 +708,8 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { case "rows", "columns": for _, child := range obj.ChildrenArray { if child.IsContainer() { - c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid grid diagram %#v. can only set %#v with no descendants (see %#v)`, obj.AbsID(), keyword, child.ChildrenArray[0].AbsID())) + c.errorf(f.LastPrimaryKey(), + fmt.Sprintf(`%#v can only be used on containers with one level of nesting right now. (%#v has nested %#v)`, keyword, child.AbsID(), child.ChildrenArray[0].ID)) } } } @@ -796,12 +797,12 @@ func (c *compiler) validateNear(g *d2graph.Graph) { func (c *compiler) validateEdges(g *d2graph.Graph) { for _, edge := range g.Edges { - if gd := edge.Src.ClosestGridDiagram(); gd != nil { - c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid diagram %#v", d2format.Format(edge.GetAstEdge()), gd.AbsID()) + if gd := edge.Src.Parent.ClosestGridDiagram(); gd != nil { + c.errorf(edge.GetAstEdge(), "edges in grid diagrams are not supported yet") continue } - if gd := edge.Dst.ClosestGridDiagram(); gd != nil { - c.errorf(edge.GetAstEdge(), "edge %#v cannot enter grid diagram %#v", d2format.Format(edge.GetAstEdge()), gd.AbsID()) + if gd := edge.Dst.Parent.ClosestGridDiagram(); gd != nil { + c.errorf(edge.GetAstEdge(), "edges in grid diagrams are not supported yet") continue } } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index a031203ea..92d8fd41e 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2299,9 +2299,9 @@ obj { hey -> c: ok `, - expErr: `d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge "a -> b" cannot enter grid diagram "hey" -d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge "c -> hey.b" cannot enter grid diagram "hey" -d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge "hey.a -> c" cannot enter grid diagram "hey"`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edges in grid diagrams are not supported yet +d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edges in grid diagrams are not supported yet +d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edges in grid diagrams are not supported yet`, }, { name: "grid_nested", @@ -2315,8 +2315,8 @@ d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge "hey.a -> c" cannot en d.invalid descendant } `, - expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid diagram "hey". can only set "rows" with no descendants (see "hey.d.invalid descendant") -d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid diagram "hey". can only set "columns" with no descendants (see "hey.d.invalid descendant")`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: "rows" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant") +d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: "columns" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant")`, }, } diff --git a/d2graph/grid_diagram.go b/d2graph/grid_diagram.go index ec41e0460..9f1aff9e9 100644 --- a/d2graph/grid_diagram.go +++ b/d2graph/grid_diagram.go @@ -6,11 +6,11 @@ func (obj *Object) IsGridDiagram() bool { } func (obj *Object) ClosestGridDiagram() *Object { - if obj.Parent == nil { + if obj == nil { return nil } - if obj.Parent.IsGridDiagram() { - return obj.Parent + if obj.IsGridDiagram() { + return obj } return obj.Parent.ClosestGridDiagram() } diff --git a/d2layouts/d2grid/grid_diagram.go b/d2layouts/d2grid/grid_diagram.go index 6b4d8dfb3..bb68aad79 100644 --- a/d2layouts/d2grid/grid_diagram.go +++ b/d2layouts/d2grid/grid_diagram.go @@ -2,6 +2,7 @@ package d2grid import ( "strconv" + "strings" "oss.terrastruct.com/d2/d2graph" ) @@ -79,7 +80,7 @@ func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) { obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = make([]*d2graph.Object, 0) for _, child := range gd.objects { - obj.Children[child.ID] = child + obj.Children[strings.ToLower(child.ID)] = child obj.ChildrenArray = append(obj.ChildrenArray, child) } graph.Objects = append(graph.Objects, gd.objects...) diff --git a/d2layouts/d2near/layout.go b/d2layouts/d2near/layout.go index 082a0e296..695fda827 100644 --- a/d2layouts/d2near/layout.go +++ b/d2layouts/d2near/layout.go @@ -34,7 +34,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, constantNears []*d2graph.Obje if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") { // The z-index for constant nears does not matter, as it will not collide g.Objects = append(g.Objects, obj) - obj.Parent.Children[obj.ID] = obj + obj.Parent.Children[strings.ToLower(obj.ID)] = obj obj.Parent.ChildrenArray = append(obj.Parent.ChildrenArray, obj) } } diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go index a2c7df0a5..0da870f19 100644 --- a/d2layouts/d2sequence/layout.go +++ b/d2layouts/d2sequence/layout.go @@ -171,12 +171,12 @@ func cleanup(g *d2graph.Graph, sequenceDiagrams map[string]*sequenceDiagram, obj obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = make([]*d2graph.Object, 0) for _, child := range sd.actors { - obj.Children[child.ID] = child + obj.Children[strings.ToLower(child.ID)] = child obj.ChildrenArray = append(obj.ChildrenArray, child) } for _, child := range sd.groups { if child.Parent.AbsID() == obj.AbsID() { - obj.Children[child.ID] = child + obj.Children[strings.ToLower(child.ID)] = child obj.ChildrenArray = append(obj.ChildrenArray, child) } } diff --git a/testdata/d2compiler/TestCompile/grid_edge.exp.json b/testdata/d2compiler/TestCompile/grid_edge.exp.json index dee805205..d8b36c51b 100644 --- a/testdata/d2compiler/TestCompile/grid_edge.exp.json +++ b/testdata/d2compiler/TestCompile/grid_edge.exp.json @@ -5,15 +5,15 @@ "errs": [ { "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,2:1:17-2:7:23", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edge \"a -> b\" cannot enter grid diagram \"hey\"" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edges in grid diagrams are not supported yet" }, { "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,4:1:27-4:11:37", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edge \"c -> hey.b\" cannot enter grid diagram \"hey\"" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edges in grid diagrams are not supported yet" }, { "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,5:1:39-5:11:49", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edge \"hey.a -> c\" cannot enter grid diagram \"hey\"" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edges in grid diagrams are not supported yet" } ] } diff --git a/testdata/d2compiler/TestCompile/grid_nested.exp.json b/testdata/d2compiler/TestCompile/grid_nested.exp.json index a45781692..ff55b27e7 100644 --- a/testdata/d2compiler/TestCompile/grid_nested.exp.json +++ b/testdata/d2compiler/TestCompile/grid_nested.exp.json @@ -5,11 +5,11 @@ "errs": [ { "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,1:1:8-1:10:17", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: invalid grid diagram \"hey\". can only set \"rows\" with no descendants (see \"hey.d.invalid descendant\")" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: \"rows\" can only be used on containers with one level of nesting right now. (\"hey.d\" has nested \"invalid descendant\")" }, { "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,2:1:19-2:13:31", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: invalid grid diagram \"hey\". can only set \"columns\" with no descendants (see \"hey.d.invalid descendant\")" + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: \"columns\" can only be used on containers with one level of nesting right now. (\"hey.d\" has nested \"invalid descendant\")" } ] } From a75d4dd0b91ce8f86254f26866684e86bff225f6 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Thu, 6 Apr 2023 15:43:03 -0700 Subject: [PATCH 31/31] update keywords rows -> grid-rows --- d2compiler/compile.go | 26 +++++++------- d2compiler/compile_test.go | 22 ++++++------ d2graph/d2graph.go | 34 +++++++++---------- d2graph/grid_diagram.go | 2 +- d2layouts/d2grid/grid_diagram.go | 10 +++--- d2oracle/edit.go | 12 +++---- e2etests/testdata/files/dagger_grid.d2 | 2 +- e2etests/testdata/files/executive_grid.d2 | 2 +- e2etests/testdata/files/grid_tests.d2 | 32 ++++++++--------- e2etests/testdata/files/teleport_grid.d2 | 10 +++--- testdata/d2compiler/TestCompile/grid.exp.json | 34 +++++++++---------- .../d2compiler/TestCompile/grid_edge.exp.json | 6 ++-- .../TestCompile/grid_negative.exp.json | 4 +-- .../TestCompile/grid_nested.exp.json | 8 ++--- 14 files changed, 102 insertions(+), 102 deletions(-) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 07d450257..c3d721bc7 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -363,32 +363,32 @@ func (c *compiler) compileReserved(attrs *d2graph.Attributes, f *d2ir.Field) { } attrs.Constraint.Value = scalar.ScalarString() attrs.Constraint.MapKey = f.LastPrimaryKey() - case "rows": + case "grid-rows": v, err := strconv.Atoi(scalar.ScalarString()) if err != nil { - c.errorf(scalar, "non-integer rows %#v: %s", scalar.ScalarString(), err) + c.errorf(scalar, "non-integer grid-rows %#v: %s", scalar.ScalarString(), err) return } if v <= 0 { - c.errorf(scalar, "rows must be a positive integer: %#v", scalar.ScalarString()) + c.errorf(scalar, "grid-rows must be a positive integer: %#v", scalar.ScalarString()) return } - attrs.Rows = &d2graph.Scalar{} - attrs.Rows.Value = scalar.ScalarString() - attrs.Rows.MapKey = f.LastPrimaryKey() - case "columns": + attrs.GridRows = &d2graph.Scalar{} + attrs.GridRows.Value = scalar.ScalarString() + attrs.GridRows.MapKey = f.LastPrimaryKey() + case "grid-columns": v, err := strconv.Atoi(scalar.ScalarString()) if err != nil { - c.errorf(scalar, "non-integer columns %#v: %s", scalar.ScalarString(), err) + c.errorf(scalar, "non-integer grid-columns %#v: %s", scalar.ScalarString(), err) return } if v <= 0 { - c.errorf(scalar, "columns must be a positive integer: %#v", scalar.ScalarString()) + c.errorf(scalar, "grid-columns must be a positive integer: %#v", scalar.ScalarString()) return } - attrs.Columns = &d2graph.Scalar{} - attrs.Columns.Value = scalar.ScalarString() - attrs.Columns.MapKey = f.LastPrimaryKey() + attrs.GridColumns = &d2graph.Scalar{} + attrs.GridColumns.Value = scalar.ScalarString() + attrs.GridColumns.MapKey = f.LastPrimaryKey() } if attrs.Link != nil && attrs.Tooltip != nil { @@ -705,7 +705,7 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { if !in && arrowheadIn { c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid shape, can only set "%s" for arrowheads`, obj.Attributes.Shape.Value)) } - case "rows", "columns": + case "grid-rows", "grid-columns": for _, child := range obj.ChildrenArray { if child.IsContainer() { c.errorf(f.LastPrimaryKey(), diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 92d8fd41e..89b8b04f2 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2271,27 +2271,27 @@ obj { { name: "grid", text: `hey: { - rows: 200 - columns: 230 + grid-rows: 200 + grid-columns: 230 } `, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "200", g.Objects[0].Attributes.Rows.Value) + tassert.Equal(t, "200", g.Objects[0].Attributes.GridRows.Value) }, }, { name: "grid_negative", text: `hey: { - rows: 200 - columns: -200 + grid-rows: 200 + grid-columns: -200 } `, - expErr: `d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a positive integer: "-200"`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:16: grid-columns must be a positive integer: "-200"`, }, { name: "grid_edge", text: `hey: { - rows: 1 + grid-rows: 1 a -> b } c -> hey.b @@ -2306,8 +2306,8 @@ d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edges in grid diagrams are { name: "grid_nested", text: `hey: { - rows: 200 - columns: 200 + grid-rows: 200 + grid-columns: 200 a b @@ -2315,8 +2315,8 @@ d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edges in grid diagrams are d.invalid descendant } `, - expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: "rows" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant") -d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: "columns" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant")`, + expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: "grid-rows" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant") +d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: "grid-columns" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant")`, }, } diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index d9ae9a89d..be2892e97 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -133,8 +133,8 @@ type Attributes struct { Direction Scalar `json:"direction"` Constraint Scalar `json:"constraint"` - Rows *Scalar `json:"rows,omitempty"` - Columns *Scalar `json:"columns,omitempty"` + GridRows *Scalar `json:"gridRows,omitempty"` + GridColumns *Scalar `json:"gridColumns,omitempty"` } // TODO references at the root scope should have their Scope set to root graph AST @@ -1531,21 +1531,21 @@ var ReservedKeywords2 map[string]struct{} // Non Style/Holder keywords. var SimpleReservedKeywords = map[string]struct{}{ - "label": {}, - "desc": {}, - "shape": {}, - "icon": {}, - "constraint": {}, - "tooltip": {}, - "link": {}, - "near": {}, - "width": {}, - "height": {}, - "direction": {}, - "top": {}, - "left": {}, - "rows": {}, - "columns": {}, + "label": {}, + "desc": {}, + "shape": {}, + "icon": {}, + "constraint": {}, + "tooltip": {}, + "link": {}, + "near": {}, + "width": {}, + "height": {}, + "direction": {}, + "top": {}, + "left": {}, + "grid-rows": {}, + "grid-columns": {}, } // ReservedKeywordHolders are reserved keywords that are meaningless on its own and exist solely to hold a set of reserved keywords diff --git a/d2graph/grid_diagram.go b/d2graph/grid_diagram.go index 9f1aff9e9..6c40667a5 100644 --- a/d2graph/grid_diagram.go +++ b/d2graph/grid_diagram.go @@ -2,7 +2,7 @@ package d2graph func (obj *Object) IsGridDiagram() bool { return obj != nil && obj.Attributes != nil && - (obj.Attributes.Rows != nil || obj.Attributes.Columns != nil) + (obj.Attributes.GridRows != nil || obj.Attributes.GridColumns != nil) } func (obj *Object) ClosestGridDiagram() *Object { diff --git a/d2layouts/d2grid/grid_diagram.go b/d2layouts/d2grid/grid_diagram.go index bb68aad79..264bc07cc 100644 --- a/d2layouts/d2grid/grid_diagram.go +++ b/d2layouts/d2grid/grid_diagram.go @@ -23,11 +23,11 @@ type gridDiagram struct { func newGridDiagram(root *d2graph.Object) *gridDiagram { gd := gridDiagram{root: root, objects: root.ChildrenArray} - if root.Attributes.Rows != nil { - gd.rows, _ = strconv.Atoi(root.Attributes.Rows.Value) + if root.Attributes.GridRows != nil { + gd.rows, _ = strconv.Atoi(root.Attributes.GridRows.Value) } - if root.Attributes.Columns != nil { - gd.columns, _ = strconv.Atoi(root.Attributes.Columns.Value) + if root.Attributes.GridColumns != nil { + gd.columns, _ = strconv.Atoi(root.Attributes.GridColumns.Value) } if gd.rows != 0 && gd.columns != 0 { @@ -38,7 +38,7 @@ func newGridDiagram(root *d2graph.Object) *gridDiagram { // . │ g h i │ │ c f i │ // . └───────┘ └───────┘ // if keyword rows is first, make it row-directed, if columns is first it is column-directed - if root.Attributes.Rows.MapKey.Range.Before(root.Attributes.Columns.MapKey.Range) { + if root.Attributes.GridRows.MapKey.Range.Before(root.Attributes.GridColumns.MapKey.Range) { gd.rowDirected = true } diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 376634e22..58aaab1b6 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -314,14 +314,14 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error { attrs.Left.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } - case "rows": - if attrs.Rows != nil && attrs.Rows.MapKey != nil { - attrs.Rows.MapKey.SetScalar(mk.Value.ScalarBox()) + case "grid-rows": + if attrs.GridRows != nil && attrs.GridRows.MapKey != nil { + attrs.GridRows.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } - case "columns": - if attrs.Columns != nil && attrs.Columns.MapKey != nil { - attrs.Columns.MapKey.SetScalar(mk.Value.ScalarBox()) + case "grid-columns": + if attrs.GridColumns != nil && attrs.GridColumns.MapKey != nil { + attrs.GridColumns.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } case "source-arrowhead", "target-arrowhead": diff --git a/e2etests/testdata/files/dagger_grid.d2 b/e2etests/testdata/files/dagger_grid.d2 index dc9d8debe..2f6167c06 100644 --- a/e2etests/testdata/files/dagger_grid.d2 +++ b/e2etests/testdata/files/dagger_grid.d2 @@ -1,4 +1,4 @@ -rows: 5 +grid-rows: 5 style.fill: black flow1: "" { diff --git a/e2etests/testdata/files/executive_grid.d2 b/e2etests/testdata/files/executive_grid.d2 index 4a3a5c3ab..a5178fbd6 100644 --- a/e2etests/testdata/files/executive_grid.d2 +++ b/e2etests/testdata/files/executive_grid.d2 @@ -1,4 +1,4 @@ -rows: 3 +grid-rows: 3 Executive Services.width: 1000 diff --git a/e2etests/testdata/files/grid_tests.d2 b/e2etests/testdata/files/grid_tests.d2 index 501c9ea24..aab1481e9 100644 --- a/e2etests/testdata/files/grid_tests.d2 +++ b/e2etests/testdata/files/grid_tests.d2 @@ -1,5 +1,5 @@ rows 1: { - rows: 1 + grid-rows: 1 a b c @@ -10,7 +10,7 @@ rows 1: { } columns 1: { - columns: 1 + grid-columns: 1 a b c @@ -21,7 +21,7 @@ columns 1: { } rows 2: { - rows: 2 + grid-rows: 2 a b c @@ -32,7 +32,7 @@ rows 2: { } columns 2: { - columns: 2 + grid-columns: 2 a b c @@ -43,8 +43,8 @@ columns 2: { } rows 2 columns 2: { - rows: 2 - columns: 2 + grid-rows: 2 + grid-columns: 2 a b @@ -56,8 +56,8 @@ rows 2 columns 2: { } columns 2 rows 2: { - columns: 2 - rows: 2 + grid-columns: 2 + grid-rows: 2 a b @@ -69,8 +69,8 @@ columns 2 rows 2: { } rows 3 columns 3: { - rows: 3 - columns: 3 + grid-rows: 3 + grid-columns: 3 a b @@ -82,8 +82,8 @@ rows 3 columns 3: { } columns 3 rows 3: { - columns: 3 - rows: 3 + grid-columns: 3 + grid-rows: 3 a b @@ -95,7 +95,7 @@ columns 3 rows 3: { } rows 3: { - rows: 3 + grid-rows: 3 a b @@ -107,7 +107,7 @@ rows 3: { } columns 3: { - columns: 3 + grid-columns: 3 a b @@ -119,8 +119,8 @@ columns 3: { } widths heights: { - rows: 3 - columns: 3 + grid-rows: 3 + grid-columns: 3 a w200.width: 200 b h300.height: 300 diff --git a/e2etests/testdata/files/teleport_grid.d2 b/e2etests/testdata/files/teleport_grid.d2 index baec9fe60..d0e737513 100644 --- a/e2etests/testdata/files/teleport_grid.d2 +++ b/e2etests/testdata/files/teleport_grid.d2 @@ -9,7 +9,7 @@ teleport -> identity provider teleport <- identity provider users: "" { - columns: 1 + grid-columns: 1 Engineers: { shape: circle @@ -22,7 +22,7 @@ users: "" { } via: "" { - columns: 1 + grid-columns: 1 https: "HTTPS://" kubectl: "> kubectl" @@ -32,7 +32,7 @@ via: "" { } teleport: Teleport { - rows: 2 + grid-rows: 2 inp: |md # Identity Native Proxy @@ -45,7 +45,7 @@ teleport: Teleport { } jita: "Just-in-time Access via" { - rows: 1 + grid-rows: 1 Slack.icon: https://icons.terrastruct.com/dev%2Fslack.svg Mattermost @@ -55,7 +55,7 @@ jita: "Just-in-time Access via" { } infra: Infrastructure { - rows: 2 + grid-rows: 2 ssh.icon: https://icons.terrastruct.com/essentials%2F112-server.svg Kubernetes.icon: https://icons.terrastruct.com/azure%2F_Companies%2FKubernetes.svg diff --git a/testdata/d2compiler/TestCompile/grid.exp.json b/testdata/d2compiler/TestCompile/grid.exp.json index 8cad38d75..8b4e621bc 100644 --- a/testdata/d2compiler/TestCompile/grid.exp.json +++ b/testdata/d2compiler/TestCompile/grid.exp.json @@ -3,11 +3,11 @@ "name": "", "isFolderOnly": false, "ast": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-4:0:34", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-4:0:44", "nodes": [ { "map_key": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-3:1:33", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-3:1:43", "key": { "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:0:0-0:3:3", "path": [ @@ -27,21 +27,21 @@ "primary": {}, "value": { "map": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:5:5-3:0:32", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,0:5:5-3:0:42", "nodes": [ { "map_key": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:10:17", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:15:22", "key": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:5:12", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:10:17", "path": [ { "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:5:12", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:1:8-1:10:17", "value": [ { - "string": "rows", - "raw_string": "rows" + "string": "grid-rows", + "raw_string": "grid-rows" } ] } @@ -51,7 +51,7 @@ "primary": {}, "value": { "number": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:7:14-1:10:17", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,1:12:19-1:15:22", "raw": "200", "value": "200" } @@ -60,17 +60,17 @@ }, { "map_key": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:19-2:13:31", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:24-2:18:41", "key": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:19-2:8:26", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:24-2:13:36", "path": [ { "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:19-2:8:26", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:1:24-2:13:36", "value": [ { - "string": "columns", - "raw_string": "columns" + "string": "grid-columns", + "raw_string": "grid-columns" } ] } @@ -80,7 +80,7 @@ "primary": {}, "value": { "number": { - "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:10:28-2:13:31", + "range": "d2/testdata/d2compiler/TestCompile/grid.d2,2:15:38-2:18:41", "raw": "230", "value": "230" } @@ -165,10 +165,10 @@ "constraint": { "value": "" }, - "rows": { + "gridRows": { "value": "200" }, - "columns": { + "gridColumns": { "value": "230" } }, diff --git a/testdata/d2compiler/TestCompile/grid_edge.exp.json b/testdata/d2compiler/TestCompile/grid_edge.exp.json index d8b36c51b..52a77accb 100644 --- a/testdata/d2compiler/TestCompile/grid_edge.exp.json +++ b/testdata/d2compiler/TestCompile/grid_edge.exp.json @@ -4,15 +4,15 @@ "ioerr": null, "errs": [ { - "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,2:1:17-2:7:23", + "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,2:1:22-2:7:28", "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edges in grid diagrams are not supported yet" }, { - "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,4:1:27-4:11:37", + "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,4:1:32-4:11:42", "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edges in grid diagrams are not supported yet" }, { - "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,5:1:39-5:11:49", + "range": "d2/testdata/d2compiler/TestCompile/grid_edge.d2,5:1:44-5:11:54", "errmsg": "d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edges in grid diagrams are not supported yet" } ] diff --git a/testdata/d2compiler/TestCompile/grid_negative.exp.json b/testdata/d2compiler/TestCompile/grid_negative.exp.json index 5551871da..7999bc2b6 100644 --- a/testdata/d2compiler/TestCompile/grid_negative.exp.json +++ b/testdata/d2compiler/TestCompile/grid_negative.exp.json @@ -4,8 +4,8 @@ "ioerr": null, "errs": [ { - "range": "d2/testdata/d2compiler/TestCompile/grid_negative.d2,2:10:28-2:14:32", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:11: columns must be a positive integer: \"-200\"" + "range": "d2/testdata/d2compiler/TestCompile/grid_negative.d2,2:15:38-2:19:42", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:16: grid-columns must be a positive integer: \"-200\"" } ] } diff --git a/testdata/d2compiler/TestCompile/grid_nested.exp.json b/testdata/d2compiler/TestCompile/grid_nested.exp.json index ff55b27e7..c8db27f4f 100644 --- a/testdata/d2compiler/TestCompile/grid_nested.exp.json +++ b/testdata/d2compiler/TestCompile/grid_nested.exp.json @@ -4,12 +4,12 @@ "ioerr": null, "errs": [ { - "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,1:1:8-1:10:17", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: \"rows\" can only be used on containers with one level of nesting right now. (\"hey.d\" has nested \"invalid descendant\")" + "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,1:1:8-1:15:22", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: \"grid-rows\" can only be used on containers with one level of nesting right now. (\"hey.d\" has nested \"invalid descendant\")" }, { - "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,2:1:19-2:13:31", - "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: \"columns\" can only be used on containers with one level of nesting right now. (\"hey.d\" has nested \"invalid descendant\")" + "range": "d2/testdata/d2compiler/TestCompile/grid_nested.d2,2:1:24-2:18:41", + "errmsg": "d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: \"grid-columns\" can only be used on containers with one level of nesting right now. (\"hey.d\" has nested \"invalid descendant\")" } ] }