diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md
index fd17e49e7..a5c689214 100644
--- a/ci/release/changelogs/next.md
+++ b/ci/release/changelogs/next.md
@@ -11,3 +11,4 @@
#### Bugfixes ⛑️
- Fixes `d2` erroring on malformed user paths (`fdopendir` error). [util-go#10](https://github.com/terrastruct/util-go/pull/10)
+- Arrowhead labels being set without maps wasn't being picked up. [#1015](https://github.com/terrastruct/d2/pull/1015)
diff --git a/d2compiler/compile.go b/d2compiler/compile.go
index 729f2e46f..95efdfaad 100644
--- a/d2compiler/compile.go
+++ b/d2compiler/compile.go
@@ -488,9 +488,7 @@ func (c *compiler) compileEdgeField(edge *d2graph.Edge, f *d2ir.Field) {
}
if f.Name == "source-arrowhead" || f.Name == "target-arrowhead" {
- if f.Map() != nil {
- c.compileArrowheads(edge, f)
- }
+ c.compileArrowheads(edge, f)
}
}
@@ -508,21 +506,23 @@ func (c *compiler) compileArrowheads(edge *d2graph.Edge, f *d2ir.Field) {
c.compileLabel(attrs, f)
}
- for _, f2 := range f.Map().Fields {
- keyword := strings.ToLower(f2.Name)
- _, isReserved := d2graph.SimpleReservedKeywords[keyword]
- if isReserved {
- c.compileReserved(attrs, f2)
- continue
- } else if f2.Name == "style" {
- if f2.Map() == nil {
+ if f.Map() != nil {
+ for _, f2 := range f.Map().Fields {
+ keyword := strings.ToLower(f2.Name)
+ _, isReserved := d2graph.SimpleReservedKeywords[keyword]
+ if isReserved {
+ c.compileReserved(attrs, f2)
+ continue
+ } else if f2.Name == "style" {
+ if f2.Map() == nil {
+ continue
+ }
+ c.compileStyle(attrs, f2.Map())
+ continue
+ } else {
+ c.errorf(f2.LastRef().AST(), `source-arrowhead/target-arrowhead map keys must be reserved keywords`)
continue
}
- c.compileStyle(attrs, f2.Map())
- continue
- } else {
- c.errorf(f2.LastRef().AST(), `source-arrowhead/target-arrowhead map keys must be reserved keywords`)
- continue
}
}
}
diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go
index e40083b34..159e64289 100644
--- a/d2compiler/compile_test.go
+++ b/d2compiler/compile_test.go
@@ -971,6 +971,17 @@ x -> y: {
}
},
},
+ {
+ name: "edge_arrowhead_primary",
+
+ text: `x -> y: {
+ source-arrowhead: Reisner's Rule of Conceptual Inertia
+}
+`,
+ assertions: func(t *testing.T, g *d2graph.Graph) {
+ assert.String(t, "Reisner's Rule of Conceptual Inertia", g.Edges[0].SrcArrowhead.Label.Value)
+ },
+ },
{
name: "edge_arrowhead_fields",
diff --git a/e2etests-cli/testdata/TestCLI_E2E/internal_linked_pdf.exp.pdf b/e2etests-cli/testdata/TestCLI_E2E/internal_linked_pdf.exp.pdf
index 595dff4ba..5127f7cd9 100644
Binary files a/e2etests-cli/testdata/TestCLI_E2E/internal_linked_pdf.exp.pdf and b/e2etests-cli/testdata/TestCLI_E2E/internal_linked_pdf.exp.pdf differ
diff --git a/e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json b/e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json
index 13319f524..f73d1c5e5 100644
--- a/e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json
+++ b/e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json
@@ -91,7 +91,7 @@
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
- "srcLabel": "",
+ "srcLabel": "1",
"dst": "b",
"dstArrow": "diamond",
"dstLabel": "*",
diff --git a/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg
index 72e6bcb43..148c8c2e5 100644
--- a/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg
+++ b/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg
@@ -1,16 +1,16 @@
-
\ No newline at end of file
diff --git a/e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json b/e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json
index b03f9f6ef..4f431b28c 100644
--- a/e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json
+++ b/e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json
@@ -91,7 +91,7 @@
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
- "srcLabel": "",
+ "srcLabel": "1",
"dst": "b",
"dstArrow": "diamond",
"dstLabel": "*",
diff --git a/e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg
index e7fb7d6ed..a28ee28ea 100644
--- a/e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg
+++ b/e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg
@@ -1,16 +1,16 @@
-ab To err is human, to moo bovine*
+ .d2-1589714364 .fill-N1{fill:#0A0F25;}
+ .d2-1589714364 .fill-N2{fill:#676C7E;}
+ .d2-1589714364 .fill-N3{fill:#9499AB;}
+ .d2-1589714364 .fill-N4{fill:#CFD2DD;}
+ .d2-1589714364 .fill-N5{fill:#DEE1EB;}
+ .d2-1589714364 .fill-N6{fill:#EEF1F8;}
+ .d2-1589714364 .fill-N7{fill:#FFFFFF;}
+ .d2-1589714364 .fill-B1{fill:#0D32B2;}
+ .d2-1589714364 .fill-B2{fill:#0D32B2;}
+ .d2-1589714364 .fill-B3{fill:#E3E9FD;}
+ .d2-1589714364 .fill-B4{fill:#E3E9FD;}
+ .d2-1589714364 .fill-B5{fill:#EDF0FD;}
+ .d2-1589714364 .fill-B6{fill:#F7F8FE;}
+ .d2-1589714364 .fill-AA2{fill:#4A6FF3;}
+ .d2-1589714364 .fill-AA4{fill:#EDF0FD;}
+ .d2-1589714364 .fill-AA5{fill:#F7F8FE;}
+ .d2-1589714364 .fill-AB4{fill:#EDF0FD;}
+ .d2-1589714364 .fill-AB5{fill:#F7F8FE;}
+ .d2-1589714364 .stroke-N1{stroke:#0A0F25;}
+ .d2-1589714364 .stroke-N2{stroke:#676C7E;}
+ .d2-1589714364 .stroke-N3{stroke:#9499AB;}
+ .d2-1589714364 .stroke-N4{stroke:#CFD2DD;}
+ .d2-1589714364 .stroke-N5{stroke:#DEE1EB;}
+ .d2-1589714364 .stroke-N6{stroke:#EEF1F8;}
+ .d2-1589714364 .stroke-N7{stroke:#FFFFFF;}
+ .d2-1589714364 .stroke-B1{stroke:#0D32B2;}
+ .d2-1589714364 .stroke-B2{stroke:#0D32B2;}
+ .d2-1589714364 .stroke-B3{stroke:#E3E9FD;}
+ .d2-1589714364 .stroke-B4{stroke:#E3E9FD;}
+ .d2-1589714364 .stroke-B5{stroke:#EDF0FD;}
+ .d2-1589714364 .stroke-B6{stroke:#F7F8FE;}
+ .d2-1589714364 .stroke-AA2{stroke:#4A6FF3;}
+ .d2-1589714364 .stroke-AA4{stroke:#EDF0FD;}
+ .d2-1589714364 .stroke-AA5{stroke:#F7F8FE;}
+ .d2-1589714364 .stroke-AB4{stroke:#EDF0FD;}
+ .d2-1589714364 .stroke-AB5{stroke:#F7F8FE;}
+ .d2-1589714364 .background-color-N1{background-color:#0A0F25;}
+ .d2-1589714364 .background-color-N2{background-color:#676C7E;}
+ .d2-1589714364 .background-color-N3{background-color:#9499AB;}
+ .d2-1589714364 .background-color-N4{background-color:#CFD2DD;}
+ .d2-1589714364 .background-color-N5{background-color:#DEE1EB;}
+ .d2-1589714364 .background-color-N6{background-color:#EEF1F8;}
+ .d2-1589714364 .background-color-N7{background-color:#FFFFFF;}
+ .d2-1589714364 .background-color-B1{background-color:#0D32B2;}
+ .d2-1589714364 .background-color-B2{background-color:#0D32B2;}
+ .d2-1589714364 .background-color-B3{background-color:#E3E9FD;}
+ .d2-1589714364 .background-color-B4{background-color:#E3E9FD;}
+ .d2-1589714364 .background-color-B5{background-color:#EDF0FD;}
+ .d2-1589714364 .background-color-B6{background-color:#F7F8FE;}
+ .d2-1589714364 .background-color-AA2{background-color:#4A6FF3;}
+ .d2-1589714364 .background-color-AA4{background-color:#EDF0FD;}
+ .d2-1589714364 .background-color-AA5{background-color:#F7F8FE;}
+ .d2-1589714364 .background-color-AB4{background-color:#EDF0FD;}
+ .d2-1589714364 .background-color-AB5{background-color:#F7F8FE;}
+ .d2-1589714364 .color-N1{color:#0A0F25;}
+ .d2-1589714364 .color-N2{color:#676C7E;}
+ .d2-1589714364 .color-N3{color:#9499AB;}
+ .d2-1589714364 .color-N4{color:#CFD2DD;}
+ .d2-1589714364 .color-N5{color:#DEE1EB;}
+ .d2-1589714364 .color-N6{color:#EEF1F8;}
+ .d2-1589714364 .color-N7{color:#FFFFFF;}
+ .d2-1589714364 .color-B1{color:#0D32B2;}
+ .d2-1589714364 .color-B2{color:#0D32B2;}
+ .d2-1589714364 .color-B3{color:#E3E9FD;}
+ .d2-1589714364 .color-B4{color:#E3E9FD;}
+ .d2-1589714364 .color-B5{color:#EDF0FD;}
+ .d2-1589714364 .color-B6{color:#F7F8FE;}
+ .d2-1589714364 .color-AA2{color:#4A6FF3;}
+ .d2-1589714364 .color-AA4{color:#EDF0FD;}
+ .d2-1589714364 .color-AA5{color:#F7F8FE;}
+ .d2-1589714364 .color-AB4{color:#EDF0FD;}
+ .d2-1589714364 .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}]]>ab To err is human, to moo bovine1*
\ No newline at end of file
diff --git a/testdata/d2compiler/TestCompile/edge_arrowhead_primary.exp.json b/testdata/d2compiler/TestCompile/edge_arrowhead_primary.exp.json
new file mode 100644
index 000000000..c089d0c7d
--- /dev/null
+++ b/testdata/d2compiler/TestCompile/edge_arrowhead_primary.exp.json
@@ -0,0 +1,270 @@
+{
+ "graph": {
+ "name": "",
+ "isFolderOnly": false,
+ "ast": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:0:0-3:0:69",
+ "nodes": [
+ {
+ "map_key": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:0:0-2:1:68",
+ "edges": [
+ {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:0:0-0:6:6",
+ "src": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:0:0-0:2:2",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:0:0-0:1:1",
+ "value": [
+ {
+ "string": "x",
+ "raw_string": "x"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "src_arrow": "",
+ "dst": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:4:4-0:6:6",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:5:5-0:6:6",
+ "value": [
+ {
+ "string": "y",
+ "raw_string": "y"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "dst_arrow": ">"
+ }
+ ],
+ "primary": {},
+ "value": {
+ "map": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:8:8-2:0:67",
+ "nodes": [
+ {
+ "map_key": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,1:2:12-1:56:66",
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,1:2:12-1:18:28",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,1:2:12-1:18:28",
+ "value": [
+ {
+ "string": "source-arrowhead",
+ "raw_string": "source-arrowhead"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "primary": {},
+ "value": {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,1:20:30-1:56:66",
+ "value": [
+ {
+ "string": "Reisner's Rule of Conceptual Inertia",
+ "raw_string": "Reisner's Rule of Conceptual Inertia"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ },
+ "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": [
+ {
+ "index": 0,
+ "minWidth": 0,
+ "minHeight": 0,
+ "label_dimensions": {
+ "width": 0,
+ "height": 0
+ },
+ "isCurve": false,
+ "src_arrow": false,
+ "srcArrowhead": {
+ "label": {
+ "value": "Reisner's Rule of Conceptual Inertia"
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": ""
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "dst_arrow": true,
+ "references": [
+ {
+ "map_key_edge_index": 0
+ }
+ ],
+ "attributes": {
+ "label": {
+ "value": ""
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": ""
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "zIndex": 0
+ }
+ ],
+ "objects": [
+ {
+ "id": "x",
+ "id_val": "x",
+ "label_dimensions": {
+ "width": 0,
+ "height": 0
+ },
+ "references": [
+ {
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:0:0-0:2:2",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:0:0-0:1:1",
+ "value": [
+ {
+ "string": "x",
+ "raw_string": "x"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "key_path_index": 0,
+ "map_key_edge_index": 0
+ }
+ ],
+ "attributes": {
+ "label": {
+ "value": "x"
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": "rectangle"
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "zIndex": 0
+ },
+ {
+ "id": "y",
+ "id_val": "y",
+ "label_dimensions": {
+ "width": 0,
+ "height": 0
+ },
+ "references": [
+ {
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:4:4-0:6:6",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/edge_arrowhead_primary.d2,0:5:5-0:6:6",
+ "value": [
+ {
+ "string": "y",
+ "raw_string": "y"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "key_path_index": 0,
+ "map_key_edge_index": 0
+ }
+ ],
+ "attributes": {
+ "label": {
+ "value": "y"
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": "rectangle"
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "zIndex": 0
+ }
+ ]
+ },
+ "err": null
+}
diff --git a/testdata/d2exporter/TestExport/connection/arrowhead.exp.json b/testdata/d2exporter/TestExport/connection/arrowhead.exp.json
index ea00bee66..d6912f2b7 100644
--- a/testdata/d2exporter/TestExport/connection/arrowhead.exp.json
+++ b/testdata/d2exporter/TestExport/connection/arrowhead.exp.json
@@ -89,7 +89,7 @@
"id": "(x -> y)[0]",
"src": "x",
"srcArrow": "none",
- "srcLabel": "",
+ "srcLabel": "If you've done six impossible things before breakfast, why not round it",
"dst": "y",
"dstArrow": "filled-diamond",
"dstLabel": "A man with one watch knows what time it is.",