From 098a27c64a69934ddc510b1330f1d54695fdfbc1 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sat, 24 Aug 2024 20:02:52 -0600 Subject: [PATCH] d2ir: extend icon links --- d2ast/d2ast.go | 4 + d2ir/compile.go | 27 ++- e2etests-cli/main_test.go | 3 +- .../TestCLI_E2E/import_icon_relative.exp.svg | 157 +++++++++--------- 4 files changed, 106 insertions(+), 85 deletions(-) diff --git a/d2ast/d2ast.go b/d2ast/d2ast.go index d11f9735fc..f82da677da 100644 --- a/d2ast/d2ast.go +++ b/d2ast/d2ast.go @@ -1431,3 +1431,7 @@ func (i *Import) PathWithPre() string { } return path.Join(i.Pre, i.Path[0].Unbox().ScalarString()) } + +func (i *Import) Dir() string { + return path.Dir(i.PathWithPre()) +} diff --git a/d2ir/compile.go b/d2ir/compile.go index 20af53d62c..9da3a7a4ea 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -1,7 +1,10 @@ package d2ir import ( + "html" "io/fs" + "net/url" + "path" "strconv" "strings" @@ -558,7 +561,8 @@ func (c *compiler) compileMap(dst *Map, ast, scopeAST *d2ast.Map) { } OverlayMap(dst, impn.Map()) - c.extendLinks(dst, ParentField(dst)) + impDir := n.Import.Dir() + c.extendLinks(dst, ParentField(dst), impDir) if impnf, ok := impn.(*Field); ok { if impnf.Primary_ != nil { @@ -862,7 +866,8 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) { } } OverlayMap(f.Map(), n) - c.extendLinks(f.Map(), f) + impDir := refctx.Key.Value.Import.Dir() + c.extendLinks(f.Map(), f, impDir) switch NodeBoardKind(f) { case BoardScenario, BoardStep: c.overlayClasses(f.Map()) @@ -895,9 +900,10 @@ func (c *compiler) ignoreLazyGlob(n Node) bool { return false } -// When importing a file, all of its board links need to be extended to reflect their new path -func (c *compiler) extendLinks(m *Map, importF *Field) { +// When importing a file, all of its board and icon links need to be extended to reflect their new path +func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) { nodeBoardKind := NodeBoardKind(m) + importIDA := IDA(importF) for _, f := range m.Fields { if f.Name == "link" { if nodeBoardKind != "" { @@ -914,14 +920,23 @@ func (c *compiler) extendLinks(m *Map, importF *Field) { continue } - importIDA := IDA(importF) extendedIDA := append(importIDA, linkIDA[1:]...) kp := d2ast.MakeKeyPath(extendedIDA) s := d2format.Format(kp) f.Primary_.Value = d2ast.MakeValueBox(d2ast.FlatUnquotedString(s)).ScalarBox().Unbox() } + if f.Name == "icon" { + val := f.Primary().Value.ScalarString() + u, err := url.Parse(html.UnescapeString(val)) + isRemoteImg := err == nil && strings.HasPrefix(u.Scheme, "http") + if isRemoteImg { + continue + } + val = path.Join(importDir, val) + f.Primary_.Value = d2ast.MakeValueBox(d2ast.FlatUnquotedString(val)).ScalarBox().Unbox() + } if f.Map() != nil { - c.extendLinks(f.Map(), importF) + c.extendLinks(f.Map(), importF, importDir) } } } diff --git a/e2etests-cli/main_test.go b/e2etests-cli/main_test.go index 98053162d7..d051530fa6 100644 --- a/e2etests-cli/main_test.go +++ b/e2etests-cli/main_test.go @@ -715,8 +715,9 @@ steps: { name: "import_icon_relative", run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { writeFile(t, dir, "hello-world.d2", `...@asdf/x`) - writeFile(t, filepath.Join(dir, "asdf"), "x.d2", `y: { icon: ./blah.svg }`) + writeFile(t, filepath.Join(dir, "asdf"), "x.d2", `y: { icon: ./blah.svg }; z: { icon: ../root.svg }`) writeFile(t, filepath.Join(dir, "asdf"), "blah.svg", ``) + writeFile(t, dir, "root.svg", ``) err := runTestMain(t, ctx, dir, env, filepath.Join(dir, "hello-world.d2")) assert.Success(t, err) svg := readFile(t, dir, "hello-world.svg") diff --git a/e2etests-cli/testdata/TestCLI_E2E/import_icon_relative.exp.svg b/e2etests-cli/testdata/TestCLI_E2E/import_icon_relative.exp.svg index 71db9bfde0..5a3562a0f3 100644 --- a/e2etests-cli/testdata/TestCLI_E2E/import_icon_relative.exp.svg +++ b/e2etests-cli/testdata/TestCLI_E2E/import_icon_relative.exp.svg @@ -1,10 +1,10 @@ -y - + .d2-1179270023 .fill-N1{fill:#0A0F25;} + .d2-1179270023 .fill-N2{fill:#676C7E;} + .d2-1179270023 .fill-N3{fill:#9499AB;} + .d2-1179270023 .fill-N4{fill:#CFD2DD;} + .d2-1179270023 .fill-N5{fill:#DEE1EB;} + .d2-1179270023 .fill-N6{fill:#EEF1F8;} + .d2-1179270023 .fill-N7{fill:#FFFFFF;} + .d2-1179270023 .fill-B1{fill:#0D32B2;} + .d2-1179270023 .fill-B2{fill:#0D32B2;} + .d2-1179270023 .fill-B3{fill:#E3E9FD;} + .d2-1179270023 .fill-B4{fill:#E3E9FD;} + .d2-1179270023 .fill-B5{fill:#EDF0FD;} + .d2-1179270023 .fill-B6{fill:#F7F8FE;} + .d2-1179270023 .fill-AA2{fill:#4A6FF3;} + .d2-1179270023 .fill-AA4{fill:#EDF0FD;} + .d2-1179270023 .fill-AA5{fill:#F7F8FE;} + .d2-1179270023 .fill-AB4{fill:#EDF0FD;} + .d2-1179270023 .fill-AB5{fill:#F7F8FE;} + .d2-1179270023 .stroke-N1{stroke:#0A0F25;} + .d2-1179270023 .stroke-N2{stroke:#676C7E;} + .d2-1179270023 .stroke-N3{stroke:#9499AB;} + .d2-1179270023 .stroke-N4{stroke:#CFD2DD;} + .d2-1179270023 .stroke-N5{stroke:#DEE1EB;} + .d2-1179270023 .stroke-N6{stroke:#EEF1F8;} + .d2-1179270023 .stroke-N7{stroke:#FFFFFF;} + .d2-1179270023 .stroke-B1{stroke:#0D32B2;} + .d2-1179270023 .stroke-B2{stroke:#0D32B2;} + .d2-1179270023 .stroke-B3{stroke:#E3E9FD;} + .d2-1179270023 .stroke-B4{stroke:#E3E9FD;} + .d2-1179270023 .stroke-B5{stroke:#EDF0FD;} + .d2-1179270023 .stroke-B6{stroke:#F7F8FE;} + .d2-1179270023 .stroke-AA2{stroke:#4A6FF3;} + .d2-1179270023 .stroke-AA4{stroke:#EDF0FD;} + .d2-1179270023 .stroke-AA5{stroke:#F7F8FE;} + .d2-1179270023 .stroke-AB4{stroke:#EDF0FD;} + .d2-1179270023 .stroke-AB5{stroke:#F7F8FE;} + .d2-1179270023 .background-color-N1{background-color:#0A0F25;} + .d2-1179270023 .background-color-N2{background-color:#676C7E;} + .d2-1179270023 .background-color-N3{background-color:#9499AB;} + .d2-1179270023 .background-color-N4{background-color:#CFD2DD;} + .d2-1179270023 .background-color-N5{background-color:#DEE1EB;} + .d2-1179270023 .background-color-N6{background-color:#EEF1F8;} + .d2-1179270023 .background-color-N7{background-color:#FFFFFF;} + .d2-1179270023 .background-color-B1{background-color:#0D32B2;} + .d2-1179270023 .background-color-B2{background-color:#0D32B2;} + .d2-1179270023 .background-color-B3{background-color:#E3E9FD;} + .d2-1179270023 .background-color-B4{background-color:#E3E9FD;} + .d2-1179270023 .background-color-B5{background-color:#EDF0FD;} + .d2-1179270023 .background-color-B6{background-color:#F7F8FE;} + .d2-1179270023 .background-color-AA2{background-color:#4A6FF3;} + .d2-1179270023 .background-color-AA4{background-color:#EDF0FD;} + .d2-1179270023 .background-color-AA5{background-color:#F7F8FE;} + .d2-1179270023 .background-color-AB4{background-color:#EDF0FD;} + .d2-1179270023 .background-color-AB5{background-color:#F7F8FE;} + .d2-1179270023 .color-N1{color:#0A0F25;} + .d2-1179270023 .color-N2{color:#676C7E;} + .d2-1179270023 .color-N3{color:#9499AB;} + .d2-1179270023 .color-N4{color:#CFD2DD;} + .d2-1179270023 .color-N5{color:#DEE1EB;} + .d2-1179270023 .color-N6{color:#EEF1F8;} + .d2-1179270023 .color-N7{color:#FFFFFF;} + .d2-1179270023 .color-B1{color:#0D32B2;} + .d2-1179270023 .color-B2{color:#0D32B2;} + .d2-1179270023 .color-B3{color:#E3E9FD;} + .d2-1179270023 .color-B4{color:#E3E9FD;} + .d2-1179270023 .color-B5{color:#EDF0FD;} + .d2-1179270023 .color-B6{color:#F7F8FE;} + .d2-1179270023 .color-AA2{color:#4A6FF3;} + .d2-1179270023 .color-AA4{color:#EDF0FD;} + .d2-1179270023 .color-AA5{color:#F7F8FE;} + .d2-1179270023 .color-AB4{color:#EDF0FD;} + .d2-1179270023 .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}]]>yz + +