diff --git a/ci/release/template/man/d2.1 b/ci/release/template/man/d2.1 index 6d548cb0f..faf28e1fa 100644 --- a/ci/release/template/man/d2.1 +++ b/ci/release/template/man/d2.1 @@ -9,7 +9,9 @@ .Op Fl -watch Ar false .Op Fl -theme Em 0 .Ar file.d2 -.Op Ar file.svg|file.png +.Op Ar file.svg +| +.Op Ar file.png .Nm d2 .Op Fl -watch Ar false .Op Fl -theme Em 0 @@ -21,7 +23,11 @@ .Nm compiles and renders .Ar file.d2 -to svg or png. +to +.Ar file.svg +, +.Ar file.png +.Ns . .Pp Pass - to have .Nm diff --git a/cmd/d2/help.go b/cmd/d2/help.go index 69e33bb98..6531f1379 100644 --- a/cmd/d2/help.go +++ b/cmd/d2/help.go @@ -17,7 +17,7 @@ func help(ms *xmain.State) { fmt.Fprintf(ms.Stdout, `Usage: %s [--watch=false] [--theme=0] file.d2 [file.svg|file.png] -%[1]s compiles and renders file.d2 to svg or png. +%[1]s compiles and renders file.d2 to file.svg, file.png. Use - to have d2 read from stdin or write to stdout. Flags: diff --git a/cmd/d2/main.go b/cmd/d2/main.go index e8108cb74..fb21c1bfa 100644 --- a/cmd/d2/main.go +++ b/cmd/d2/main.go @@ -119,11 +119,12 @@ func run(ctx context.Context, ms *xmain.State) (err error) { if err != nil { return err } - defer func() { - cleanupErr := pw.Cleanup() - if cleanupErr != nil { - ms.Log.Error.Printf("error cleaning up Playwright: %v", cleanupErr.Error()) + defer func() error { + err = pw.Cleanup() + if err != nil { + return err } + return nil }() } @@ -180,23 +181,23 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, input if err != nil { return nil, err } - outputImage, err := plugin.PostProcess(ctx, svg) + out, err := plugin.PostProcess(ctx, svg) if err != nil { return nil, err } if filepath.Ext(outputPath) == ".png" { - outputImage, err = png.ConvertSVG(ms, page, outputImage) + out, err = png.ConvertSVG(ms, page, out) if err != nil { return nil, err } } - err = ms.WritePath(outputPath, outputImage) + err = ms.WritePath(outputPath, out) if err != nil { return nil, err } - return svg, nil + return out, nil } // newExt must include leading . diff --git a/cmd/d2/watch.go b/cmd/d2/watch.go index 8207641de..1680a2521 100644 --- a/cmd/d2/watch.go +++ b/cmd/d2/watch.go @@ -337,7 +337,7 @@ func (w *watcher) compileLoop(ctx context.Context) error { w.broadcast(&compileResult{ Err: broadcastErr.Error(), }) - return fmt.Errorf("Playwright could not be restarted: %w", err) + continue } w.pw = newPW } diff --git a/lib/png/png.go b/lib/png/png.go index a3fd64792..52fe23a7f 100644 --- a/lib/png/png.go +++ b/lib/png/png.go @@ -1,11 +1,8 @@ package png import ( - "bytes" "encoding/base64" "fmt" - "os" - "os/exec" "strings" _ "embed" @@ -20,19 +17,19 @@ type Playwright struct { Page playwright.Page } -func (pw *Playwright) RestartBrowser() (newPW Playwright, err error) { - if err = pw.Browser.Close(); err != nil { - return Playwright{}, err +func (pw *Playwright) RestartBrowser() (Playwright, error) { + if err := pw.Browser.Close(); err != nil { + return Playwright{}, fmt.Errorf("failed to close Playwright browser: %w", err) } return startPlaywright(pw.PW) } func (pw *Playwright) Cleanup() error { if err := pw.Browser.Close(); err != nil { - return err + return fmt.Errorf("failed to close Playwright browser: %w", err) } if err := pw.PW.Stop(); err != nil { - return err + return fmt.Errorf("failed to stop Playwright: %w", err) } return nil } @@ -40,15 +37,15 @@ func (pw *Playwright) Cleanup() error { func startPlaywright(pw *playwright.Playwright) (Playwright, error) { browser, err := pw.Chromium.Launch() if err != nil { - return Playwright{}, err + return Playwright{}, fmt.Errorf("failed to launch Chromium: %w", err) } context, err := browser.NewContext() if err != nil { - return Playwright{}, err + return Playwright{}, fmt.Errorf("failed to start new Playwright browser context: %w", err) } page, err := context.NewPage() if err != nil { - return Playwright{}, err + return Playwright{}, fmt.Errorf("failed to start new Playwright page: %w", err) } return Playwright{ PW: pw, @@ -58,39 +55,14 @@ func startPlaywright(pw *playwright.Playwright) (Playwright, error) { } func InitPlaywright() (Playwright, error) { - // check if playwright driver/browsers are installed and up to date - // https://github.com/playwright-community/playwright-go/blob/8e8f670b5fa7ba5365ae4bfc123fea4aac359763/run.go#L64. - driver, err := playwright.NewDriver(&playwright.RunOptions{}) + err := playwright.Install(&playwright.RunOptions{Verbose: false}) if err != nil { - return Playwright{}, err - } - _, err = os.Stat(driver.DriverBinaryLocation) - if err != nil { - if os.IsNotExist(err) { - err = playwright.Install() - if err != nil { - return Playwright{}, err - } - } else { - return Playwright{}, fmt.Errorf("could not access Playwright binary location: %v\nerror: %w\nplease report this issue here: https://github.com/terrastruct/d2/issues/new", driver.DriverBinaryLocation, err) - } - } - - cmd := exec.Command(driver.DriverBinaryLocation, "--version") - output, err := cmd.Output() - if err != nil { - return Playwright{}, fmt.Errorf("error getting Playwright version: %w\nplease report this issue here: https://github.com/terrastruct/d2/issues/new", err) - } - if !bytes.Contains(output, []byte(driver.Version)) { - err = playwright.Install() - if err != nil { - return Playwright{}, err - } + return Playwright{}, fmt.Errorf("failed to install Playwright: %w", err) } pw, err := playwright.Run() if err != nil { - return Playwright{}, err + return Playwright{}, fmt.Errorf("failed to run Playwright: %w", err) } return startPlaywright(pw) } @@ -100,7 +72,7 @@ var genPNGScript string const pngPrefix = "data:image/png;base64," -func ConvertSVG(ms *xmain.State, page playwright.Page, svg []byte) (outputImage []byte, err error) { +func ConvertSVG(ms *xmain.State, page playwright.Page, svg []byte) ([]byte, error) { encodedSVG := base64.StdEncoding.EncodeToString(svg) pngInterface, err := page.Evaluate(genPNGScript, "data:image/svg+xml;charset=utf-8;base64,"+encodedSVG) if err != nil {