diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index f1db4276e..024a0b550 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -10,6 +10,7 @@ - Latex: Backslashes in Latex blocks do not escape [#2232](https://github.com/terrastruct/d2/pull/2232) - This is a breaking change. Previously Latex blocks required escaping the backslash. So for older D2 versions, you should remove the excess backslashes. +- Links: non-http url scheme links are supported (e.g. `x.link: vscode://file/`) [#2237](https://github.com/terrastruct/d2/issues/2237) #### Bugfixes ⛑️ diff --git a/d2compiler/compile.go b/d2compiler/compile.go index be7150d1a..fafc71e96 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -1215,7 +1215,7 @@ func (c *compiler) validateBoardLinks(g *d2graph.Graph) { } u, err := url.Parse(html.UnescapeString(obj.Link.Value)) - isRemote := err == nil && strings.HasPrefix(u.Scheme, "http") + isRemote := err == nil && u.Scheme != "" if isRemote { continue } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index d644b7fa9..b48bcc93c 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -1511,6 +1511,22 @@ x -> y: { } }, }, + { + name: "non_url_link", + + text: `x: { + link: vscode://file//Users/pmoura/logtalk/examples/searching/hill_climbing1.lgt:35:0 +} +`, + assertions: func(t *testing.T, g *d2graph.Graph) { + if len(g.Objects) != 1 { + t.Fatal(g.Objects) + } + if g.Objects[0].Link.Value != "vscode://file//Users/pmoura/logtalk/examples/searching/hill_climbing1.lgt:35:0" { + t.Fatal(g.Objects[0].Link.Value) + } + }, + }, { name: "import_url_link", diff --git a/d2ir/compile.go b/d2ir/compile.go index a112a99e3..f0baff4da 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -977,7 +977,7 @@ func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) { val := f.Primary().Value.ScalarString() u, err := url.Parse(html.UnescapeString(val)) - isRemote := err == nil && strings.HasPrefix(u.Scheme, "http") + isRemote := err == nil && u.Scheme != "" if isRemote { continue } @@ -1015,7 +1015,7 @@ func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) { continue } u, err := url.Parse(html.UnescapeString(val)) - isRemoteImg := err == nil && strings.HasPrefix(u.Scheme, "http") + isRemoteImg := err == nil && u.Scheme != "" if isRemoteImg { continue } diff --git a/testdata/d2compiler/TestCompile/non_url_link.exp.json b/testdata/d2compiler/TestCompile/non_url_link.exp.json new file mode 100644 index 000000000..68e35e0bd --- /dev/null +++ b/testdata/d2compiler/TestCompile/non_url_link.exp.json @@ -0,0 +1,148 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,0:0:0-3:0:94", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,0:0:0-2:1:93", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,0:3:3-2:1:93", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,1:2:7-1:86:91", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,1:2:7-1:6:11", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,1:2:7-1:6:11", + "value": [ + { + "string": "link", + "raw_string": "link" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,1:8:13-1:86:91", + "value": [ + { + "string": "vscode://file//Users/pmoura/logtalk/examples/searching/hill_climbing1.lgt:35:0", + "raw_string": "vscode://file//Users/pmoura/logtalk/examples/searching/hill_climbing1.lgt:35:0" + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/non_url_link.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "link": { + "value": "vscode://file//Users/pmoura/logtalk/examples/searching/hill_climbing1.lgt:35:0" + }, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}