wip gif export

This commit is contained in:
Júlio César Batista 2023-04-13 18:50:39 -03:00
parent 588398a4df
commit 9fc5a5f4ce
No known key found for this signature in database
GPG key ID: 10C4B861BF314878
3 changed files with 35 additions and 16 deletions

View file

@ -1,10 +1,18 @@
package d2cli
import "path/filepath"
import (
"path/filepath"
)
type exportExtension string
var KNOWN_EXTENSIONS = []string{".svg", ".png", ".pptx", ".pdf"}
const GIF = ".gif"
const PNG = ".png"
const PPTX = ".pptx"
const PDF = ".pdf"
const SVG = ".svg"
var KNOWN_EXTENSIONS = []string{SVG, PNG, PDF, PPTX, GIF}
func getExportExtension(outputPath string) exportExtension {
ext := filepath.Ext(outputPath)
@ -14,17 +22,17 @@ func getExportExtension(outputPath string) exportExtension {
}
}
// default is svg
return exportExtension(".svg")
return exportExtension(SVG)
}
func (ex exportExtension) supportsAnimation() bool {
return ex == ".svg"
return ex == SVG || ex == GIF
}
func (ex exportExtension) requiresPngRenderer() bool {
return ex == ".png" || ex == ".pdf" || ex == ".pptx"
func (ex exportExtension) requiresPNGRenderer() bool {
return ex == PNG || ex == PDF || ex == PPTX || ex == GIF
}
func (ex exportExtension) supportsDarkTheme() bool {
return ex == ".svg"
return ex == SVG
}

View file

@ -67,7 +67,7 @@ func TestOutputFormat(t *testing.T) {
assert.Equal(t, tc.extension, extension)
assert.Equal(t, tc.supportsAnimation, extension.supportsAnimation())
assert.Equal(t, tc.supportsDarkTheme, extension.supportsDarkTheme())
assert.Equal(t, tc.requiresPngRender, extension.requiresPngRenderer())
assert.Equal(t, tc.requiresPngRender, extension.requiresPNGRenderer())
})
}
}

View file

@ -38,6 +38,7 @@ import (
"oss.terrastruct.com/d2/lib/pptx"
"oss.terrastruct.com/d2/lib/textmeasure"
"oss.terrastruct.com/d2/lib/version"
"oss.terrastruct.com/d2/lib/xgif"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
@ -190,9 +191,10 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
if outputPath != "-" {
outputPath = ms.AbsPath(outputPath)
if *animateIntervalFlag > 0 && !outputFormat.supportsAnimation() {
return xmain.UsageErrorf("-animate-interval can only be used when exporting to SVG.\nYou provided: %s", filepath.Ext(outputPath))
return xmain.UsageErrorf("-animate-interval can only be used when exporting to SVG or GIF.\nYou provided: %s", filepath.Ext(outputPath))
} else if *animateIntervalFlag <= 0 && outputFormat == GIF {
return xmain.UsageErrorf("-animate-interval must be greater than 0 for GIF outputs.\nYou provided: %d", *animateIntervalFlag)
}
}
match := d2themescatalog.Find(*themeFlag)
@ -242,7 +244,7 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
}
}
var pw png.Playwright
if outputFormat.requiresPngRenderer() {
if outputFormat.requiresPNGRenderer() {
pw, err = png.InitPlaywright()
if err != nil {
return err
@ -351,8 +353,9 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
return nil, false, err
}
switch filepath.Ext(outputPath) {
case ".pdf":
ext := getExportExtension(outputPath)
switch ext {
case PDF:
pageMap := buildBoardIDToIndex(diagram, nil, nil)
pdf, err := renderPDF(ctx, ms, plugin, renderOpts, outputPath, page, ruler, diagram, nil, nil, pageMap)
if err != nil {
@ -361,7 +364,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
dur := time.Since(start)
ms.Log.Success.Printf("successfully compiled %s to %s in %s", ms.HumanPath(inputPath), ms.HumanPath(outputPath), dur)
return pdf, true, nil
case ".pptx":
case PPTX:
var username string
if user, err := user.Current(); err == nil {
username = user.Username
@ -398,11 +401,19 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
if err != nil {
return nil, false, err
}
// TODO: test GIF with 1 frame
var out []byte
if len(boards) > 0 {
out = boards[0]
if animateInterval > 0 {
if ext == GIF {
tl, br := diagram.NestedBoundingBox()
width := png.SCALE*(br.X-tl.X) + renderOpts.Pad*2
height := png.SCALE*(br.Y-tl.Y) + renderOpts.Pad*2
out, err = xgif.AnimatePNGs(boards, width, height, int(animateInterval))
} else {
out, err = d2animate.Wrap(diagram, boards, renderOpts, int(animateInterval))
}
if err != nil {
return nil, false, err
}
@ -599,7 +610,7 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
}
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) {
toPNG := filepath.Ext(outputPath) == ".png"
toPNG := getExportExtension(outputPath).requiresPNGRenderer()
svg, err := d2svg.Render(diagram, &d2svg.RenderOpts{
Pad: opts.Pad,
Sketch: opts.Sketch,