diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md
index 57e5b1145..e6f26b305 100644
--- a/ci/release/changelogs/next.md
+++ b/ci/release/changelogs/next.md
@@ -17,3 +17,4 @@
- Error reported when no actors are declared in sequence diagram. [#886](https://github.com/terrastruct/d2/pull/886)
- Fixed img bundling on image shapes. [#889](https://github.com/terrastruct/d2/issues/889)
- `class` shape as sequence diagram actors had wrong colors. [#899](https://github.com/terrastruct/d2/issues/899)
+- Fix regression in last release where some hex codes were not working. [#922](https://github.com/terrastruct/d2/pull/922)
diff --git a/d2compiler/compile.go b/d2compiler/compile.go
index 05d05786d..9de5f12c8 100644
--- a/d2compiler/compile.go
+++ b/d2compiler/compile.go
@@ -189,7 +189,7 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
}
}
scopeObjIDA := d2ir.IDA(fr.Context.ScopeMap)
- scopeObj, _ := obj.Graph.Root.HasChildIDVal(scopeObjIDA)
+ scopeObj := obj.Graph.Root.EnsureChildIDVal(scopeObjIDA)
obj.References = append(obj.References, d2graph.Reference{
Key: fr.KeyPath,
KeyPathIndex: fr.KeyPathIndex(),
@@ -427,7 +427,7 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
edge.Attributes.Label.MapKey = e.LastPrimaryKey()
for _, er := range e.References {
scopeObjIDA := d2ir.IDA(er.Context.ScopeMap)
- scopeObj, _ := edge.Src.Graph.Root.HasChildIDVal(scopeObjIDA)
+ scopeObj := edge.Src.Graph.Root.EnsureChildIDVal(scopeObjIDA)
edge.References = append(edge.References, d2graph.EdgeReference{
Edge: er.Context.Edge,
MapKey: er.Context.Key,
diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go
index 3e2e6dc53..52da3f916 100644
--- a/d2compiler/compile_test.go
+++ b/d2compiler/compile_test.go
@@ -1378,6 +1378,21 @@ x -> y: {
}
},
},
+ {
+ name: "nil_scope_obj_regression",
+
+ text: `a
+b: {
+ _.a
+}
+`,
+ assertions: func(t *testing.T, g *d2graph.Graph) {
+ tassert.Equal(t, "a", g.Objects[0].ID)
+ for _, ref := range g.Objects[0].References {
+ tassert.NotNil(t, ref.ScopeObj)
+ }
+ },
+ },
{
name: "path_link",
diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go
index ae3bfc74d..a19487ee2 100644
--- a/d2graph/d2graph.go
+++ b/d2graph/d2graph.go
@@ -560,15 +560,15 @@ func (obj *Object) HasChild(ids []string) (*Object, bool) {
return child, true
}
-// Keep in sync with HasChild.
-func (obj *Object) HasChildIDVal(ids []string) (*Object, bool) {
+// Keep in sync with EnsureChild.
+func (obj *Object) EnsureChildIDVal(ids []string) *Object {
if len(ids) == 0 {
- return obj, true
+ return obj
}
if len(ids) == 1 && ids[0] != "style" {
_, ok := ReservedKeywords[ids[0]]
if ok {
- return obj, true
+ return obj
}
}
@@ -583,13 +583,13 @@ func (obj *Object) HasChildIDVal(ids []string) (*Object, bool) {
}
}
if child == nil {
- return nil, false
+ child = obj.newObject(id)
}
if len(ids) >= 1 {
- return child.HasChildIDVal(ids)
+ return child.EnsureChildIDVal(ids)
}
- return child, true
+ return child
}
func (obj *Object) HasEdge(mk *d2ast.Key) (*Edge, bool) {
diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go
index 9f37917e3..b105e4e72 100644
--- a/d2ir/d2ir.go
+++ b/d2ir/d2ir.go
@@ -1027,11 +1027,12 @@ func parentPrimaryKey(n Node) *d2ast.Key {
return nil
}
+// IDA returns the absolute path to n from the nearest board root.
func IDA(n Node) (ida []string) {
for {
f, ok := n.(*Field)
if ok {
- if f.Root() {
+ if f.Root() || NodeBoardKind(f) != "" {
reverseIDA(ida)
return ida
}
diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go
index f4c3d0ce4..0050b7f91 100644
--- a/d2oracle/edit_test.go
+++ b/d2oracle/edit_test.go
@@ -3309,6 +3309,22 @@ d
exp: `a: {
_.b -> c -> _.b
}
+`,
+ },
+ {
+ name: "container_multiple_refs_with_underscore",
+
+ text: `a
+b: {
+ _.a
+}
+`,
+ key: `a`,
+ newKey: `b.a`,
+
+ exp: `b: {
+ a
+}
`,
},
}
diff --git a/e2etests/regression_test.go b/e2etests/regression_test.go
index af9855070..7b72d354a 100644
--- a/e2etests/regression_test.go
+++ b/e2etests/regression_test.go
@@ -6,6 +6,14 @@ import (
func testRegression(t *testing.T) {
tcs := []testCase{
+ {
+ // https://github.com/terrastruct/d2/issues/919
+ name: "hex-fill",
+ script: `x: {
+ style.fill: "#0D32B2"
+}
+`,
+ },
{
name: "dagre_special_ids",
script: `
diff --git a/e2etests/testdata/regression/hex-fill/dagre/board.exp.json b/e2etests/testdata/regression/hex-fill/dagre/board.exp.json
new file mode 100644
index 000000000..e845adb1c
--- /dev/null
+++ b/e2etests/testdata/regression/hex-fill/dagre/board.exp.json
@@ -0,0 +1,88 @@
+{
+ "name": "",
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "x",
+ "type": "rectangle",
+ "pos": {
+ "x": 0,
+ "y": 0
+ },
+ "width": 53,
+ "height": 66,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#0D32B2",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 8,
+ "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/regression/hex-fill/dagre/sketch.exp.svg b/e2etests/testdata/regression/hex-fill/dagre/sketch.exp.svg
new file mode 100644
index 000000000..14369948f
--- /dev/null
+++ b/e2etests/testdata/regression/hex-fill/dagre/sketch.exp.svg
@@ -0,0 +1,23 @@
+
\ No newline at end of file
diff --git a/e2etests/testdata/regression/hex-fill/elk/board.exp.json b/e2etests/testdata/regression/hex-fill/elk/board.exp.json
new file mode 100644
index 000000000..6f464573e
--- /dev/null
+++ b/e2etests/testdata/regression/hex-fill/elk/board.exp.json
@@ -0,0 +1,88 @@
+{
+ "name": "",
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "x",
+ "type": "rectangle",
+ "pos": {
+ "x": 12,
+ "y": 12
+ },
+ "width": 53,
+ "height": 66,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#0D32B2",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 8,
+ "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/regression/hex-fill/elk/sketch.exp.svg b/e2etests/testdata/regression/hex-fill/elk/sketch.exp.svg
new file mode 100644
index 000000000..df727da81
--- /dev/null
+++ b/e2etests/testdata/regression/hex-fill/elk/sketch.exp.svg
@@ -0,0 +1,23 @@
+x
+
+
+
\ No newline at end of file
diff --git a/lib/color/color.go b/lib/color/color.go
index 78b09ca5c..df433b878 100644
--- a/lib/color/color.go
+++ b/lib/color/color.go
@@ -11,7 +11,7 @@ import (
"github.com/mazznoer/csscolorparser"
)
-var themeColorRegex = regexp.MustCompile(`^N[1-7]|B[1-6]|AA[245]|AB[45]$`)
+var themeColorRegex = regexp.MustCompile(`^(N[1-7]|B[1-6]|AA[245]|AB[45])$`)
func IsThemeColor(colorString string) bool {
return themeColorRegex.Match([]byte(colorString))
diff --git a/testdata/d2compiler/TestCompile/nil_scope_obj_regression.exp.json b/testdata/d2compiler/TestCompile/nil_scope_obj_regression.exp.json
new file mode 100644
index 000000000..00ce55a57
--- /dev/null
+++ b/testdata/d2compiler/TestCompile/nil_scope_obj_regression.exp.json
@@ -0,0 +1,250 @@
+{
+ "graph": {
+ "name": "",
+ "ast": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,0:0:0-4:0:15",
+ "nodes": [
+ {
+ "map_key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,0:0:0-0:1:1",
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,0:0:0-0:1:1",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,0:0:0-0:1:1",
+ "value": [
+ {
+ "string": "a",
+ "raw_string": "a"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "primary": {},
+ "value": {}
+ }
+ },
+ {
+ "map_key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,1:0:2-3:1:14",
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,1:0:2-1:1:3",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,1:0:2-1:1:3",
+ "value": [
+ {
+ "string": "b",
+ "raw_string": "b"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "primary": {},
+ "value": {
+ "map": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,1:3:5-3:0:13",
+ "nodes": [
+ {
+ "map_key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,2:2:9-2:5:12",
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,2:2:9-2:5:12",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,2:2:9-2:3:10",
+ "value": [
+ {
+ "string": "_",
+ "raw_string": "_"
+ }
+ ]
+ }
+ },
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,2:4:11-2:5:12",
+ "value": [
+ {
+ "string": "a",
+ "raw_string": "a"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "primary": {},
+ "value": {}
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ },
+ "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": "a",
+ "id_val": "a",
+ "label_dimensions": {
+ "width": 0,
+ "height": 0
+ },
+ "references": [
+ {
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,0:0:0-0:1:1",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,0:0:0-0:1:1",
+ "value": [
+ {
+ "string": "a",
+ "raw_string": "a"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "key_path_index": 0,
+ "map_key_edge_index": -1
+ },
+ {
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,2:2:9-2:5:12",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,2:2:9-2:3:10",
+ "value": [
+ {
+ "string": "_",
+ "raw_string": "_"
+ }
+ ]
+ }
+ },
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,2:4:11-2:5:12",
+ "value": [
+ {
+ "string": "a",
+ "raw_string": "a"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "key_path_index": 1,
+ "map_key_edge_index": -1
+ }
+ ],
+ "attributes": {
+ "label": {
+ "value": "a"
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": "rectangle"
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "zIndex": 0
+ },
+ {
+ "id": "b",
+ "id_val": "b",
+ "label_dimensions": {
+ "width": 0,
+ "height": 0
+ },
+ "references": [
+ {
+ "key": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,1:0:2-1:1:3",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2compiler/TestCompile/nil_scope_obj_regression.d2,1:0:2-1:1:3",
+ "value": [
+ {
+ "string": "b",
+ "raw_string": "b"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "key_path_index": 0,
+ "map_key_edge_index": -1
+ }
+ ],
+ "attributes": {
+ "label": {
+ "value": "b"
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": "rectangle"
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "zIndex": 0
+ }
+ ]
+ },
+ "err": null
+}
diff --git a/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.exp.json b/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.exp.json
new file mode 100644
index 000000000..ef29483a3
--- /dev/null
+++ b/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.exp.json
@@ -0,0 +1,185 @@
+{
+ "graph": {
+ "name": "",
+ "ast": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,0:0:0-3:0:11",
+ "nodes": [
+ {
+ "map_key": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,0:0:0-2:1:10",
+ "key": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,0:0:0-0:1:1",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,0:0:0-0:1:1",
+ "value": [
+ {
+ "string": "b",
+ "raw_string": "b"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "primary": {},
+ "value": {
+ "map": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,0:3:3-2:0:9",
+ "nodes": [
+ {
+ "map_key": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,1:2:7-1:3:8",
+ "key": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,1:2:7-1:3:8",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,1:2:7-1:3:8",
+ "value": [
+ {
+ "string": "a",
+ "raw_string": "a"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "primary": {},
+ "value": {}
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ },
+ "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": "b",
+ "id_val": "b",
+ "label_dimensions": {
+ "width": 0,
+ "height": 0
+ },
+ "references": [
+ {
+ "key": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,0:0:0-0:1:1",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,0:0:0-0:1:1",
+ "value": [
+ {
+ "string": "b",
+ "raw_string": "b"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "key_path_index": 0,
+ "map_key_edge_index": -1
+ }
+ ],
+ "attributes": {
+ "label": {
+ "value": "b"
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": "rectangle"
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "zIndex": 0
+ },
+ {
+ "id": "a",
+ "id_val": "a",
+ "label_dimensions": {
+ "width": 0,
+ "height": 0
+ },
+ "references": [
+ {
+ "key": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,1:2:7-1:3:8",
+ "path": [
+ {
+ "unquoted_string": {
+ "range": "d2/testdata/d2oracle/TestMove/container_multiple_refs_with_underscore.d2,1:2:7-1:3:8",
+ "value": [
+ {
+ "string": "a",
+ "raw_string": "a"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "key_path_index": 0,
+ "map_key_edge_index": -1
+ }
+ ],
+ "attributes": {
+ "label": {
+ "value": "a"
+ },
+ "style": {},
+ "near_key": null,
+ "shape": {
+ "value": "rectangle"
+ },
+ "direction": {
+ "value": ""
+ },
+ "constraint": {
+ "value": ""
+ }
+ },
+ "zIndex": 0
+ }
+ ]
+ },
+ "err": ""
+}