diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md
index aabaaf7b8..d7ba36cb0 100644
--- a/ci/release/changelogs/next.md
+++ b/ci/release/changelogs/next.md
@@ -7,6 +7,7 @@
- `--browser` flag on CLI controls `BROWSER` environment variable for not opening browser in watch mode. [#1052](https://github.com/terrastruct/d2/pull/1052)
- `elk` layout containers no longer overlap the label with children. [#1055](https://github.com/terrastruct/d2/pull/1055)
+- Message emitted by CLI when a particular stage is taking a long time. [#1058](https://github.com/terrastruct/d2/pull/1058)
- `
` attribute of HTML in watch mode is the base file name, instead of the whole path. [#1054](https://github.com/terrastruct/d2/pull/1054)
#### Bugfixes ⛑️
diff --git a/d2cli/main.go b/d2cli/main.go
index fbf690930..dedba22b0 100644
--- a/d2cli/main.go
+++ b/d2cli/main.go
@@ -27,6 +27,7 @@ import (
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/d2themes"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
+ "oss.terrastruct.com/d2/lib/background"
"oss.terrastruct.com/d2/lib/imgbundler"
ctxlog "oss.terrastruct.com/d2/lib/log"
"oss.terrastruct.com/d2/lib/pdf"
@@ -289,10 +290,17 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, sketc
if sketch {
opts.FontFamily = go2.Pointer(d2fonts.HandDrawn)
}
+
+ cancel := background.Repeat(func() {
+ ms.Log.Info.Printf("compiling & running layout algorithms...")
+ }, time.Second*5)
+ defer cancel()
+
diagram, g, err := d2lib.Compile(ctx, string(input), opts)
if err != nil {
return nil, false, err
}
+ cancel()
pluginInfo, err := plugin.Info(ctx)
if err != nil {
diff --git a/lib/background/background.go b/lib/background/background.go
new file mode 100644
index 000000000..ad16a16fd
--- /dev/null
+++ b/lib/background/background.go
@@ -0,0 +1,28 @@
+package background
+
+import "time"
+
+func Repeat(do func(), interval time.Duration) (cancel func()) {
+ t := time.NewTicker(interval)
+ done := make(chan struct{})
+
+ go func() {
+ defer t.Stop()
+ for {
+ select {
+ case <-t.C:
+ do()
+ case <-done:
+ return
+ }
+ }
+ }()
+
+ stopped := false
+ return func() {
+ if !stopped {
+ stopped = true
+ close(done)
+ }
+ }
+}
diff --git a/lib/png/png.go b/lib/png/png.go
index ae0d08d7f..8f89c0b20 100644
--- a/lib/png/png.go
+++ b/lib/png/png.go
@@ -5,6 +5,7 @@ import (
"encoding/base64"
"fmt"
"strings"
+ "time"
_ "embed"
@@ -13,6 +14,7 @@ import (
pngstruct "github.com/dsoprea/go-png-image-structure/v2"
"github.com/playwright-community/playwright-go"
+ "oss.terrastruct.com/d2/lib/background"
"oss.terrastruct.com/d2/lib/version"
"oss.terrastruct.com/util-go/xmain"
)
@@ -82,6 +84,11 @@ var genPNGScript string
const pngPrefix = "data:image/png;base64,"
func ConvertSVG(ms *xmain.State, page playwright.Page, svg []byte) ([]byte, error) {
+ cancel := background.Repeat(func() {
+ ms.Log.Info.Printf("converting to PNG...")
+ }, time.Second*5)
+ defer cancel()
+
encodedSVG := base64.StdEncoding.EncodeToString(svg)
pngInterface, err := page.Evaluate(genPNGScript, "data:image/svg+xml;charset=utf-8;base64,"+encodedSVG)
if err != nil {