Skip to content

Commit 320acc3

Browse files
committed
cli: resolve local icon paths relative to d2 file
1 parent 939a684 commit 320acc3

File tree

2 files changed

+36
-31
lines changed

2 files changed

+36
-31
lines changed

d2cli/main.go

+22-22
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs
529529
ext := getExportExtension(outputPath)
530530
switch ext {
531531
case GIF:
532-
svg, pngs, err := renderPNGsForGIF(ctx, ms, plugin, renderOpts, ruler, page, diagram)
532+
svg, pngs, err := renderPNGsForGIF(ctx, ms, plugin, renderOpts, ruler, page, inputPath, diagram)
533533
if err != nil {
534534
return nil, false, err
535535
}
@@ -553,7 +553,7 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs
553553
path := []pdf.BoardTitle{
554554
{Name: diagram.Root.Label, BoardID: "root"},
555555
}
556-
pdf, err := renderPDF(ctx, ms, plugin, renderOpts, outputPath, page, ruler, diagram, nil, path, pageMap, diagram.Root.Label != "")
556+
pdf, err := renderPDF(ctx, ms, plugin, renderOpts, inputPath, outputPath, page, ruler, diagram, nil, path, pageMap, diagram.Root.Label != "")
557557
if err != nil {
558558
return pdf, false, err
559559
}
@@ -574,7 +574,7 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs
574574
path := []pptx.BoardTitle{
575575
{Name: "root", BoardID: "root", LinkToSlide: boardIdToIndex["root"] + 1},
576576
}
577-
svg, err := renderPPTX(ctx, ms, p, plugin, renderOpts, ruler, outputPath, page, diagram, path, boardIdToIndex)
577+
svg, err := renderPPTX(ctx, ms, p, plugin, renderOpts, ruler, inputPath, outputPath, page, diagram, path, boardIdToIndex)
578578
if err != nil {
579579
return nil, false, err
580580
}
@@ -808,7 +808,7 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
808808

809809
if !diagram.IsFolderOnly {
810810
start := time.Now()
811-
out, err := _render(ctx, ms, plugin, opts, boardOutputPath, bundle, forceAppendix, page, ruler, diagram)
811+
out, err := _render(ctx, ms, plugin, opts, inputPath, boardOutputPath, bundle, forceAppendix, page, ruler, diagram)
812812
if err != nil {
813813
return boards, err
814814
}
@@ -824,7 +824,7 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
824824

825825
func renderSingle(ctx context.Context, ms *xmain.State, compileDur time.Duration, plugin d2plugin.Plugin, opts d2svg.RenderOpts, inputPath, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([][]byte, error) {
826826
start := time.Now()
827-
out, err := _render(ctx, ms, plugin, opts, outputPath, bundle, forceAppendix, page, ruler, diagram)
827+
out, err := _render(ctx, ms, plugin, opts, inputPath, outputPath, bundle, forceAppendix, page, ruler, diagram)
828828
if err != nil {
829829
return [][]byte{}, err
830830
}
@@ -835,7 +835,7 @@ func renderSingle(ctx context.Context, ms *xmain.State, compileDur time.Duration
835835
return [][]byte{out}, nil
836836
}
837837

838-
func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([]byte, error) {
838+
func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, inputPath, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([]byte, error) {
839839
toPNG := getExportExtension(outputPath) == PNG
840840
var scale *float64
841841
if opts.Scale != nil {
@@ -865,7 +865,7 @@ func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts
865865

866866
cacheImages := ms.Env.Getenv("IMG_CACHE") == "1"
867867
l := simplelog.FromCmdLog(ms.Log)
868-
svg, bundleErr := imgbundler.BundleLocal(ctx, l, svg, cacheImages)
868+
svg, bundleErr := imgbundler.BundleLocal(ctx, l, inputPath, svg, cacheImages)
869869
if bundle {
870870
var bundleErr2 error
871871
svg, bundleErr2 = imgbundler.BundleRemote(ctx, l, svg, cacheImages)
@@ -915,7 +915,7 @@ func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts
915915
return svg, nil
916916
}
917917

918-
func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram, doc *pdf.GoFPDF, boardPath []pdf.BoardTitle, pageMap map[string]int, includeNav bool) (svg []byte, err error) {
918+
func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, inputPath, outputPath string, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram, doc *pdf.GoFPDF, boardPath []pdf.BoardTitle, pageMap map[string]int, includeNav bool) (svg []byte, err error) {
919919
var isRoot bool
920920
if doc == nil {
921921
doc = pdf.Init()
@@ -953,7 +953,7 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
953953

954954
cacheImages := ms.Env.Getenv("IMG_CACHE") == "1"
955955
l := simplelog.FromCmdLog(ms.Log)
956-
svg, bundleErr := imgbundler.BundleLocal(ctx, l, svg, cacheImages)
956+
svg, bundleErr := imgbundler.BundleLocal(ctx, l, inputPath, svg, cacheImages)
957957
svg, bundleErr2 := imgbundler.BundleRemote(ctx, l, svg, cacheImages)
958958
bundleErr = multierr.Combine(bundleErr, bundleErr2)
959959
if bundleErr != nil {
@@ -986,7 +986,7 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
986986
Name: dl.Root.Label,
987987
BoardID: strings.Join([]string{boardPath[len(boardPath)-1].BoardID, LAYERS, dl.Name}, "."),
988988
})
989-
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, doc, path, pageMap, includeNav)
989+
_, err := renderPDF(ctx, ms, plugin, opts, inputPath, "", page, ruler, dl, doc, path, pageMap, includeNav)
990990
if err != nil {
991991
return nil, err
992992
}
@@ -996,7 +996,7 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
996996
Name: dl.Root.Label,
997997
BoardID: strings.Join([]string{boardPath[len(boardPath)-1].BoardID, SCENARIOS, dl.Name}, "."),
998998
})
999-
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, doc, path, pageMap, includeNav)
999+
_, err := renderPDF(ctx, ms, plugin, opts, inputPath, "", page, ruler, dl, doc, path, pageMap, includeNav)
10001000
if err != nil {
10011001
return nil, err
10021002
}
@@ -1006,7 +1006,7 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
10061006
Name: dl.Root.Label,
10071007
BoardID: strings.Join([]string{boardPath[len(boardPath)-1].BoardID, STEPS, dl.Name}, "."),
10081008
})
1009-
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, doc, path, pageMap, includeNav)
1009+
_, err := renderPDF(ctx, ms, plugin, opts, inputPath, "", page, ruler, dl, doc, path, pageMap, includeNav)
10101010
if err != nil {
10111011
return nil, err
10121012
}
@@ -1022,7 +1022,7 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
10221022
return svg, nil
10231023
}
10241024

1025-
func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Presentation, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, outputPath string, page playwright.Page, diagram *d2target.Diagram, boardPath []pptx.BoardTitle, boardIDToIndex map[string]int) ([]byte, error) {
1025+
func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Presentation, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, inputPath, outputPath string, page playwright.Page, diagram *d2target.Diagram, boardPath []pptx.BoardTitle, boardIDToIndex map[string]int) ([]byte, error) {
10261026
var svg []byte
10271027
if !diagram.IsFolderOnly {
10281028
// gofpdf will print the png img with a slight filter
@@ -1055,7 +1055,7 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present
10551055

10561056
cacheImages := ms.Env.Getenv("IMG_CACHE") == "1"
10571057
l := simplelog.FromCmdLog(ms.Log)
1058-
svg, bundleErr := imgbundler.BundleLocal(ctx, l, svg, cacheImages)
1058+
svg, bundleErr := imgbundler.BundleLocal(ctx, l, inputPath, svg, cacheImages)
10591059
svg, bundleErr2 := imgbundler.BundleRemote(ctx, l, svg, cacheImages)
10601060
bundleErr = multierr.Combine(bundleErr, bundleErr2)
10611061
if bundleErr != nil {
@@ -1120,7 +1120,7 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present
11201120
BoardID: boardID,
11211121
LinkToSlide: boardIDToIndex[boardID] + 1,
11221122
})
1123-
_, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, path, boardIDToIndex)
1123+
_, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, inputPath, "", page, dl, path, boardIDToIndex)
11241124
if err != nil {
11251125
return nil, err
11261126
}
@@ -1132,7 +1132,7 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present
11321132
BoardID: boardID,
11331133
LinkToSlide: boardIDToIndex[boardID] + 1,
11341134
})
1135-
_, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, path, boardIDToIndex)
1135+
_, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, inputPath, "", page, dl, path, boardIDToIndex)
11361136
if err != nil {
11371137
return nil, err
11381138
}
@@ -1144,7 +1144,7 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present
11441144
BoardID: boardID,
11451145
LinkToSlide: boardIDToIndex[boardID] + 1,
11461146
})
1147-
_, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, path, boardIDToIndex)
1147+
_, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, inputPath, "", page, dl, path, boardIDToIndex)
11481148
if err != nil {
11491149
return nil, err
11501150
}
@@ -1276,7 +1276,7 @@ func buildBoardIDToIndex(diagram *d2target.Diagram, dictionary map[string]int, p
12761276
return dictionary
12771277
}
12781278

1279-
func renderPNGsForGIF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, page playwright.Page, diagram *d2target.Diagram) (svg []byte, pngs [][]byte, err error) {
1279+
func renderPNGsForGIF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, page playwright.Page, inputPath string, diagram *d2target.Diagram) (svg []byte, pngs [][]byte, err error) {
12801280
if !diagram.IsFolderOnly {
12811281

12821282
var scale *float64
@@ -1302,7 +1302,7 @@ func renderPNGsForGIF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plug
13021302

13031303
cacheImages := ms.Env.Getenv("IMG_CACHE") == "1"
13041304
l := simplelog.FromCmdLog(ms.Log)
1305-
svg, bundleErr := imgbundler.BundleLocal(ctx, l, svg, cacheImages)
1305+
svg, bundleErr := imgbundler.BundleLocal(ctx, l, inputPath, svg, cacheImages)
13061306
svg, bundleErr2 := imgbundler.BundleRemote(ctx, l, svg, cacheImages)
13071307
bundleErr = multierr.Combine(bundleErr, bundleErr2)
13081308
if bundleErr != nil {
@@ -1319,21 +1319,21 @@ func renderPNGsForGIF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plug
13191319
}
13201320

13211321
for _, dl := range diagram.Layers {
1322-
_, layerPNGs, err := renderPNGsForGIF(ctx, ms, plugin, opts, ruler, page, dl)
1322+
_, layerPNGs, err := renderPNGsForGIF(ctx, ms, plugin, opts, ruler, page, inputPath, dl)
13231323
if err != nil {
13241324
return nil, nil, err
13251325
}
13261326
pngs = append(pngs, layerPNGs...)
13271327
}
13281328
for _, dl := range diagram.Scenarios {
1329-
_, scenarioPNGs, err := renderPNGsForGIF(ctx, ms, plugin, opts, ruler, page, dl)
1329+
_, scenarioPNGs, err := renderPNGsForGIF(ctx, ms, plugin, opts, ruler, page, inputPath, dl)
13301330
if err != nil {
13311331
return nil, nil, err
13321332
}
13331333
pngs = append(pngs, scenarioPNGs...)
13341334
}
13351335
for _, dl := range diagram.Steps {
1336-
_, stepsPNGs, err := renderPNGsForGIF(ctx, ms, plugin, opts, ruler, page, dl)
1336+
_, stepsPNGs, err := renderPNGsForGIF(ctx, ms, plugin, opts, ruler, page, inputPath, dl)
13371337
if err != nil {
13381338
return nil, nil, err
13391339
}

lib/imgbundler/imgbundler.go

+14-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net/url"
1313
"os"
1414
"path"
15+
"path/filepath"
1516
"regexp"
1617
"strings"
1718
"sync"
@@ -29,20 +30,20 @@ const maxImageSize int64 = 1 << 25 // 33_554_432
2930

3031
var imageRegex = regexp.MustCompile(`<image href="([^"]+)"`)
3132

32-
func BundleLocal(ctx context.Context, l simplelog.Logger, in []byte, cacheImages bool) ([]byte, error) {
33-
return bundle(ctx, l, in, false, cacheImages)
33+
func BundleLocal(ctx context.Context, l simplelog.Logger, inputPath string, in []byte, cacheImages bool) ([]byte, error) {
34+
return bundle(ctx, l, inputPath, in, false, cacheImages)
3435
}
3536

3637
func BundleRemote(ctx context.Context, l simplelog.Logger, in []byte, cacheImages bool) ([]byte, error) {
37-
return bundle(ctx, l, in, true, cacheImages)
38+
return bundle(ctx, l, "", in, true, cacheImages)
3839
}
3940

4041
type repl struct {
4142
from []byte
4243
to []byte
4344
}
4445

45-
func bundle(ctx context.Context, l simplelog.Logger, svg []byte, isRemote, cacheImages bool) (_ []byte, err error) {
46+
func bundle(ctx context.Context, l simplelog.Logger, inputPath string, svg []byte, isRemote, cacheImages bool) (_ []byte, err error) {
4647
if isRemote {
4748
defer xdefer.Errorf(&err, "failed to bundle remote images")
4849
} else {
@@ -54,7 +55,7 @@ func bundle(ctx context.Context, l simplelog.Logger, svg []byte, isRemote, cache
5455
ctx, cancel := context.WithTimeout(ctx, time.Minute*5)
5556
defer cancel()
5657

57-
return runWorkers(ctx, l, svg, imgs, isRemote, cacheImages)
58+
return runWorkers(ctx, l, inputPath, svg, imgs, isRemote, cacheImages)
5859
}
5960

6061
// filterImageElements finds all unique image elements in imgs that are
@@ -84,7 +85,7 @@ func filterImageElements(imgs [][][]byte, isRemote bool) [][][]byte {
8485
return imgs2
8586
}
8687

87-
func runWorkers(ctx context.Context, l simplelog.Logger, svg []byte, imgs [][][]byte, isRemote, cacheImages bool) (_ []byte, err error) {
88+
func runWorkers(ctx context.Context, l simplelog.Logger, inputPath string, svg []byte, imgs [][][]byte, isRemote, cacheImages bool) (_ []byte, err error) {
8889
var wg sync.WaitGroup
8990
replc := make(chan repl)
9091

@@ -111,7 +112,7 @@ func runWorkers(ctx context.Context, l simplelog.Logger, svg []byte, imgs [][][]
111112
<-sema
112113
}()
113114

114-
bundledImage, err := worker(ctx, l, img[1], isRemote, cacheImages)
115+
bundledImage, err := worker(ctx, l, inputPath, img[1], isRemote, cacheImages)
115116
if err != nil {
116117
l.Error(fmt.Sprintf("failed to bundle %s: %v", img[1], err))
117118
errhrefsMu.Lock()
@@ -150,7 +151,7 @@ func runWorkers(ctx context.Context, l simplelog.Logger, svg []byte, imgs [][][]
150151
}
151152
}
152153

153-
func worker(ctx context.Context, l simplelog.Logger, href []byte, isRemote, cacheImages bool) ([]byte, error) {
154+
func worker(ctx context.Context, l simplelog.Logger, inputPath string, href []byte, isRemote, cacheImages bool) ([]byte, error) {
154155
if cacheImages {
155156
if hit, ok := imgCache.Load(string(href)); ok {
156157
return hit.([]byte), nil
@@ -164,7 +165,11 @@ func worker(ctx context.Context, l simplelog.Logger, href []byte, isRemote, cach
164165
buf, mimeType, err = httpGet(ctx, html.UnescapeString(string(href)))
165166
} else {
166167
l.Debug(fmt.Sprintf("reading %s from disk", string(href)))
167-
buf, err = os.ReadFile(html.UnescapeString(string(href)))
168+
path := html.UnescapeString(string(href))
169+
if inputPath != "-" && !filepath.IsAbs(path) {
170+
path = filepath.Join(filepath.Dir(inputPath), path)
171+
}
172+
buf, err = os.ReadFile(path)
168173
}
169174
if err != nil {
170175
return nil, err

0 commit comments

Comments
 (0)