pr comments
This commit is contained in:
parent
492db16e92
commit
ab81a15cfb
4 changed files with 93 additions and 52 deletions
|
|
@ -1,34 +1,42 @@
|
||||||
package d2cli
|
package d2cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
type exportExtension string
|
type exportExtension string
|
||||||
|
|
||||||
const GIF = ".gif"
|
const GIF exportExtension = ".gif"
|
||||||
const PNG = ".png"
|
const PNG exportExtension = ".png"
|
||||||
const PPTX = ".pptx"
|
const PPTX exportExtension = ".pptx"
|
||||||
const PDF = ".pdf"
|
const PDF exportExtension = ".pdf"
|
||||||
const SVG = ".svg"
|
const SVG exportExtension = ".svg"
|
||||||
|
|
||||||
var KNOWN_EXTENSIONS = []string{SVG, PNG, PDF, PPTX, GIF}
|
var SUPPORTED_EXTENSIONS = []exportExtension{SVG, PNG, PDF, PPTX, GIF}
|
||||||
|
|
||||||
func getExportExtension(outputPath string) exportExtension {
|
func getExportExtension(outputPath string) (exportExtension, error) {
|
||||||
ext := filepath.Ext(outputPath)
|
ext := filepath.Ext(outputPath)
|
||||||
for _, kext := range KNOWN_EXTENSIONS {
|
if ext == ".ppt" {
|
||||||
if kext == ext {
|
return "", fmt.Errorf("D2 does not support ppt exports, did you mean \"pptx\"?")
|
||||||
return exportExtension(ext)
|
}
|
||||||
|
for _, kext := range SUPPORTED_EXTENSIONS {
|
||||||
|
if kext == exportExtension(ext) {
|
||||||
|
return exportExtension(ext), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// default is svg
|
// default is svg
|
||||||
return exportExtension(SVG)
|
return exportExtension(SVG), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ex exportExtension) supportsAnimation() bool {
|
func (ex exportExtension) supportsAnimation() bool {
|
||||||
return ex == SVG || ex == GIF
|
return ex == SVG || ex == GIF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ex exportExtension) requiresAnimationInterval() bool {
|
||||||
|
return ex == GIF
|
||||||
|
}
|
||||||
|
|
||||||
func (ex exportExtension) requiresPNGRenderer() bool {
|
func (ex exportExtension) requiresPNGRenderer() bool {
|
||||||
return ex == PNG || ex == PDF || ex == PPTX || ex == GIF
|
return ex == PNG || ex == PDF || ex == PPTX || ex == GIF
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,50 +12,65 @@ func TestOutputFormat(t *testing.T) {
|
||||||
extension exportExtension
|
extension exportExtension
|
||||||
supportsDarkTheme bool
|
supportsDarkTheme bool
|
||||||
supportsAnimation bool
|
supportsAnimation bool
|
||||||
|
requiresAnimationInterval bool
|
||||||
requiresPngRender bool
|
requiresPngRender bool
|
||||||
}
|
}
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{
|
{
|
||||||
outputPath: "/out.svg",
|
outputPath: "/out.svg",
|
||||||
extension: ".svg",
|
extension: SVG,
|
||||||
supportsDarkTheme: true,
|
supportsDarkTheme: true,
|
||||||
supportsAnimation: true,
|
supportsAnimation: true,
|
||||||
|
requiresAnimationInterval: false,
|
||||||
requiresPngRender: false,
|
requiresPngRender: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// assumes SVG by default
|
// assumes SVG by default
|
||||||
outputPath: "/out",
|
outputPath: "/out",
|
||||||
extension: ".svg",
|
extension: SVG,
|
||||||
supportsDarkTheme: true,
|
supportsDarkTheme: true,
|
||||||
supportsAnimation: true,
|
supportsAnimation: true,
|
||||||
|
requiresAnimationInterval: false,
|
||||||
requiresPngRender: false,
|
requiresPngRender: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
outputPath: "-",
|
outputPath: "-",
|
||||||
extension: ".svg",
|
extension: SVG,
|
||||||
supportsDarkTheme: true,
|
supportsDarkTheme: true,
|
||||||
supportsAnimation: true,
|
supportsAnimation: true,
|
||||||
|
requiresAnimationInterval: false,
|
||||||
requiresPngRender: false,
|
requiresPngRender: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
outputPath: "/out.png",
|
outputPath: "/out.png",
|
||||||
extension: ".png",
|
extension: PNG,
|
||||||
supportsDarkTheme: false,
|
supportsDarkTheme: false,
|
||||||
supportsAnimation: false,
|
supportsAnimation: false,
|
||||||
|
requiresAnimationInterval: false,
|
||||||
requiresPngRender: true,
|
requiresPngRender: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
outputPath: "/out.pptx",
|
outputPath: "/out.pptx",
|
||||||
extension: ".pptx",
|
extension: PPTX,
|
||||||
supportsDarkTheme: false,
|
supportsDarkTheme: false,
|
||||||
supportsAnimation: false,
|
supportsAnimation: false,
|
||||||
|
requiresAnimationInterval: false,
|
||||||
requiresPngRender: true,
|
requiresPngRender: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
outputPath: "/out.pdf",
|
outputPath: "/out.pdf",
|
||||||
extension: ".pdf",
|
extension: PDF,
|
||||||
supportsDarkTheme: false,
|
supportsDarkTheme: false,
|
||||||
supportsAnimation: false,
|
supportsAnimation: false,
|
||||||
|
requiresAnimationInterval: false,
|
||||||
|
requiresPngRender: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
outputPath: "/out.gif",
|
||||||
|
extension: GIF,
|
||||||
|
supportsDarkTheme: false,
|
||||||
|
supportsAnimation: true,
|
||||||
|
requiresAnimationInterval: true,
|
||||||
requiresPngRender: true,
|
requiresPngRender: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -63,11 +78,17 @@ func TestOutputFormat(t *testing.T) {
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
t.Run(tc.outputPath, func(t *testing.T) {
|
t.Run(tc.outputPath, func(t *testing.T) {
|
||||||
extension := getExportExtension(tc.outputPath)
|
extension, err := getExportExtension(tc.outputPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tc.extension, extension)
|
assert.Equal(t, tc.extension, extension)
|
||||||
assert.Equal(t, tc.supportsAnimation, extension.supportsAnimation())
|
assert.Equal(t, tc.supportsAnimation, extension.supportsAnimation())
|
||||||
assert.Equal(t, tc.supportsDarkTheme, extension.supportsDarkTheme())
|
assert.Equal(t, tc.supportsDarkTheme, extension.supportsDarkTheme())
|
||||||
assert.Equal(t, tc.requiresPngRender, extension.requiresPNGRenderer())
|
assert.Equal(t, tc.requiresPngRender, extension.requiresPNGRenderer())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unsupported format
|
||||||
|
_, err := getExportExtension("/out.ppt")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Equal(t, "D2 does not support ppt exports, did you mean \"pptx\"?", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,15 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
|
||||||
inputPath = filepath.Join(inputPath, "index.d2")
|
inputPath = filepath.Join(inputPath, "index.d2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outputFormat := getExportExtension(outputPath)
|
outputFormat, err := getExportExtension(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
return xmain.UsageErrorf(err.Error())
|
||||||
|
}
|
||||||
if outputPath != "-" {
|
if outputPath != "-" {
|
||||||
outputPath = ms.AbsPath(outputPath)
|
outputPath = ms.AbsPath(outputPath)
|
||||||
if *animateIntervalFlag > 0 && !outputFormat.supportsAnimation() {
|
if *animateIntervalFlag > 0 && !outputFormat.supportsAnimation() {
|
||||||
return xmain.UsageErrorf("-animate-interval can only be used when exporting to SVG or GIF.\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 {
|
} else if *animateIntervalFlag <= 0 && outputFormat.requiresAnimationInterval() {
|
||||||
return xmain.UsageErrorf("-animate-interval must be greater than 0 for GIF outputs.\nYou provided: %d", *animateIntervalFlag)
|
return xmain.UsageErrorf("-animate-interval must be greater than 0 for GIF outputs.\nYou provided: %d", *animateIntervalFlag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -353,7 +356,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ext := getExportExtension(outputPath)
|
ext, _ := getExportExtension(outputPath)
|
||||||
switch ext {
|
switch ext {
|
||||||
case GIF:
|
case GIF:
|
||||||
svg, pngs, err := renderPNGsForGIF(ctx, ms, plugin, renderOpts, ruler, page, diagram)
|
svg, pngs, err := renderPNGsForGIF(ctx, ms, plugin, renderOpts, ruler, page, diagram)
|
||||||
|
|
@ -424,7 +427,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
|
||||||
var out []byte
|
var out []byte
|
||||||
if len(boards) > 0 {
|
if len(boards) > 0 {
|
||||||
out = boards[0]
|
out = boards[0]
|
||||||
if animateInterval > 0 && ext != GIF {
|
if animateInterval > 0 {
|
||||||
out, err = d2animate.Wrap(diagram, boards, renderOpts, int(animateInterval))
|
out, err = d2animate.Wrap(diagram, boards, renderOpts, int(animateInterval))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
|
|
@ -622,7 +625,8 @@ 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) {
|
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 := getExportExtension(outputPath) == PNG
|
ext, _ := getExportExtension(outputPath)
|
||||||
|
toPNG := ext == PNG
|
||||||
svg, err := d2svg.Render(diagram, &d2svg.RenderOpts{
|
svg, err := d2svg.Render(diagram, &d2svg.RenderOpts{
|
||||||
Pad: opts.Pad,
|
Pad: opts.Pad,
|
||||||
Sketch: opts.Sketch,
|
Sketch: opts.Sketch,
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,14 @@ layers: {
|
||||||
testdataIgnoreDiff(t, ".pdf", pdf)
|
testdataIgnoreDiff(t, ".pdf", pdf)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "export_ppt",
|
||||||
|
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {
|
||||||
|
writeFile(t, dir, "x.d2", `x -> y`)
|
||||||
|
err := runTestMain(t, ctx, dir, env, "x.d2", "x.ppt")
|
||||||
|
assert.ErrorString(t, err, `failed to wait xmain test: e2etests-cli/d2: bad usage: D2 does not support ppt exports, did you mean "pptx"?`)
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "how_to_solve_problems_pptx",
|
name: "how_to_solve_problems_pptx",
|
||||||
skipCI: true,
|
skipCI: true,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue