2022-11-17 01:41:53 +00:00
|
|
|
package png
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
_ "embed"
|
|
|
|
|
|
|
|
|
|
"github.com/playwright-community/playwright-go"
|
2022-11-21 19:05:10 +00:00
|
|
|
|
2022-11-17 19:25:07 +00:00
|
|
|
"oss.terrastruct.com/d2/lib/xmain"
|
2022-11-17 01:41:53 +00:00
|
|
|
)
|
|
|
|
|
|
2022-11-17 19:25:07 +00:00
|
|
|
type Playwright struct {
|
2022-11-17 22:55:43 +00:00
|
|
|
PW *playwright.Playwright
|
|
|
|
|
Browser playwright.Browser
|
|
|
|
|
Page playwright.Page
|
2022-11-17 19:25:07 +00:00
|
|
|
}
|
|
|
|
|
|
2022-11-21 18:46:54 +00:00
|
|
|
func (pw *Playwright) RestartBrowser() (Playwright, error) {
|
|
|
|
|
if err := pw.Browser.Close(); err != nil {
|
|
|
|
|
return Playwright{}, fmt.Errorf("failed to close Playwright browser: %w", err)
|
2022-11-17 19:25:07 +00:00
|
|
|
}
|
2022-11-18 00:41:28 +00:00
|
|
|
return startPlaywright(pw.PW)
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-18 03:02:25 +00:00
|
|
|
func (pw *Playwright) Cleanup() error {
|
|
|
|
|
if err := pw.Browser.Close(); err != nil {
|
2022-11-21 18:46:54 +00:00
|
|
|
return fmt.Errorf("failed to close Playwright browser: %w", err)
|
2022-11-18 00:41:28 +00:00
|
|
|
}
|
2022-11-18 03:02:25 +00:00
|
|
|
if err := pw.PW.Stop(); err != nil {
|
2022-11-21 18:46:54 +00:00
|
|
|
return fmt.Errorf("failed to stop Playwright: %w", err)
|
2022-11-18 00:41:28 +00:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func startPlaywright(pw *playwright.Playwright) (Playwright, error) {
|
|
|
|
|
browser, err := pw.Chromium.Launch()
|
2022-11-17 19:25:07 +00:00
|
|
|
if err != nil {
|
2022-11-21 18:46:54 +00:00
|
|
|
return Playwright{}, fmt.Errorf("failed to launch Chromium: %w", err)
|
2022-11-17 19:25:07 +00:00
|
|
|
}
|
|
|
|
|
context, err := browser.NewContext()
|
|
|
|
|
if err != nil {
|
2022-11-21 18:46:54 +00:00
|
|
|
return Playwright{}, fmt.Errorf("failed to start new Playwright browser context: %w", err)
|
2022-11-17 19:25:07 +00:00
|
|
|
}
|
|
|
|
|
page, err := context.NewPage()
|
|
|
|
|
if err != nil {
|
2022-11-21 18:46:54 +00:00
|
|
|
return Playwright{}, fmt.Errorf("failed to start new Playwright page: %w", err)
|
2022-11-17 19:25:07 +00:00
|
|
|
}
|
|
|
|
|
return Playwright{
|
2022-11-18 00:41:28 +00:00
|
|
|
PW: pw,
|
2022-11-17 22:55:43 +00:00
|
|
|
Browser: browser,
|
|
|
|
|
Page: page,
|
2022-11-17 19:25:07 +00:00
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-18 02:19:00 +00:00
|
|
|
func InitPlaywright() (Playwright, error) {
|
2022-11-21 18:46:54 +00:00
|
|
|
err := playwright.Install(&playwright.RunOptions{Verbose: false})
|
2022-11-18 21:29:30 +00:00
|
|
|
if err != nil {
|
2022-11-21 18:46:54 +00:00
|
|
|
return Playwright{}, fmt.Errorf("failed to install Playwright: %w", err)
|
2022-11-17 01:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pw, err := playwright.Run()
|
|
|
|
|
if err != nil {
|
2022-11-21 18:46:54 +00:00
|
|
|
return Playwright{}, fmt.Errorf("failed to run Playwright: %w", err)
|
2022-11-17 01:41:53 +00:00
|
|
|
}
|
2022-11-18 00:41:28 +00:00
|
|
|
return startPlaywright(pw)
|
2022-11-17 01:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//go:embed generate_png.js
|
|
|
|
|
var genPNGScript string
|
|
|
|
|
|
2022-11-18 21:29:30 +00:00
|
|
|
const pngPrefix = "data:image/png;base64,"
|
2022-11-17 19:25:07 +00:00
|
|
|
|
2022-11-21 18:46:54 +00:00
|
|
|
func ConvertSVG(ms *xmain.State, page playwright.Page, svg []byte) ([]byte, error) {
|
2022-11-17 01:41:53 +00:00
|
|
|
encodedSVG := base64.StdEncoding.EncodeToString(svg)
|
|
|
|
|
pngInterface, err := page.Evaluate(genPNGScript, "data:image/svg+xml;charset=utf-8;base64,"+encodedSVG)
|
|
|
|
|
if err != nil {
|
2022-11-21 21:24:10 +00:00
|
|
|
return nil, fmt.Errorf("failed to generate png: %w", err)
|
2022-11-17 01:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
2022-11-21 19:05:10 +00:00
|
|
|
pngString := pngInterface.(string)
|
2022-11-17 01:41:53 +00:00
|
|
|
if !strings.HasPrefix(pngString, pngPrefix) {
|
2022-11-17 22:24:59 +00:00
|
|
|
if len(pngString) > 50 {
|
|
|
|
|
pngString = pngString[0:50] + "..."
|
2022-11-17 22:13:23 +00:00
|
|
|
}
|
2022-11-21 21:24:10 +00:00
|
|
|
return nil, fmt.Errorf("invalid PNG: %q", pngString)
|
2022-11-17 01:41:53 +00:00
|
|
|
}
|
|
|
|
|
splicedPNGString := pngString[len(pngPrefix):]
|
2022-11-17 19:25:07 +00:00
|
|
|
return base64.StdEncoding.DecodeString(splicedPNGString)
|
2022-11-17 01:41:53 +00:00
|
|
|
}
|