diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 10ba72b57..58ab82b6f 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -15,3 +15,4 @@ [#159](https://github.com/terrastruct/d2/issues/159) - Fixes markdown newlines created with a trailing double space or backslash. [#214](https://github.com/terrastruct/d2/pull/214) +- Fixes images not loading in PNG exports diff --git a/cmd/d2/main.go b/cmd/d2/main.go index a5e5c39e2..d2a8c9450 100644 --- a/cmd/d2/main.go +++ b/cmd/d2/main.go @@ -18,6 +18,7 @@ import ( "oss.terrastruct.com/d2/d2renderers/textmeasure" "oss.terrastruct.com/d2/d2themes" "oss.terrastruct.com/d2/d2themes/d2themescatalog" + "oss.terrastruct.com/d2/lib/imgbundler" "oss.terrastruct.com/d2/lib/png" "oss.terrastruct.com/d2/lib/version" "oss.terrastruct.com/d2/lib/xmain" @@ -205,6 +206,12 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, theme return nil, err } + // TODO this may be desirable even for SVGs. Should make it a flag + svg, err = imgbundler.Inline(ms, svg) + if err != nil { + return nil, err + } + out := svg if filepath.Ext(outputPath) == ".png" { out, err = png.ConvertSVG(ms, page, svg) diff --git a/lib/imgbundler/imgbundler.go b/lib/imgbundler/imgbundler.go new file mode 100644 index 000000000..58dddd435 --- /dev/null +++ b/lib/imgbundler/imgbundler.go @@ -0,0 +1,95 @@ +package imgbundler + +import ( + "context" + "encoding/base64" + "fmt" + "io/ioutil" + "net/http" + "regexp" + "strings" + "sync" + "time" + + "oss.terrastruct.com/d2/lib/xmain" +) + +var imgRe = regexp.MustCompile(` +ab +`, svgURL, pngURL) + + transport = RoundTripFunc(func(req *http.Request) *http.Response { + if req.URL.String() != svgURL && req.URL.String() != pngURL { + t.Fatal(req.URL.String()) + } + var body string + switch req.URL.String() { + case svgURL: + body = `\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n` + case pngURL: + body = string(testPNGFile) + default: + t.Fatal(req.URL.String()) + } + return &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewBufferString(body)), + ContentLength: int64(len(body)), + Header: make(http.Header), + } + }) + + ms := &xmain.State{ + Name: "test", + + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, + + Env: xos.NewEnv(os.Environ()), + } + ms.Log = cmdlog.Log(ms.Env, os.Stderr) + out, err := Inline(ms, []byte(sampleSVG)) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(out), "https://") { + t.Fatal("links still exist") + } + if !strings.Contains(string(out), "image/svg+xml") { + t.Fatal("no svg image inserted") + } + if !strings.Contains(string(out), "image/png") { + t.Fatal("no png image inserted") + } +} diff --git a/lib/imgbundler/test_png.png b/lib/imgbundler/test_png.png new file mode 100644 index 000000000..f1ee3a5e7 Binary files /dev/null and b/lib/imgbundler/test_png.png differ diff --git a/out.png b/out.png new file mode 100644 index 000000000..30d10f5f3 Binary files /dev/null and b/out.png differ diff --git a/out.svg b/out.svg new file mode 100644 index 000000000..d8b27516b --- /dev/null +++ b/out.svg @@ -0,0 +1,821 @@ + +People discovery serviceAd mixerOnboarding serviceTwitter Frontend WebIphoneAndroidTimelineScorerHome RankerTimeline ServiceHome mixerManhattanGizmoduckSocial graphTweety PiePrediction ServiceHome ScorerManhattanMemcacheFetchFeatureScoringPrediction Service...etc

Timeline mixer

+
    +
  • Inject ads, who-to-follow, onboarding
  • +
  • Conversation module
  • +
  • Cursoring,pagination
  • +
  • Tweat deduplication
  • +
  • Served data logging
  • +
+
GraphQLFederated Strato Column

Tweet/user content hydration, visibility filtering

+
TLS-API (being deprecated)CrMixerEarlyBirdUtagSpaceCommunities + + +iPhone web + + +HTTP Android + + +Thrift RPC + + +Candidate Fetch + + +Feature Hydration + + +Candidate sources
\ No newline at end of file