mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-17 20:52:14 +01:00
feat(chromium): add clip options to screenshot routes
This commit is contained in:
@@ -258,6 +258,7 @@ func (b *chromiumBrowser) screenshot(ctx context.Context, logger *zap.Logger, ur
|
|||||||
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
||||||
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
||||||
// Screenshot specific.
|
// Screenshot specific.
|
||||||
|
setDeviceMetricsOverride(logger, options.Width, options.Height),
|
||||||
captureScreenshotActionFunc(logger, outputPath, options),
|
captureScreenshotActionFunc(logger, outputPath, options),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1996,6 +1996,54 @@ func TestChromiumBrowser_screenshot(t *testing.T) {
|
|||||||
"no emulated media type",
|
"no emulated media type",
|
||||||
"no wait delay",
|
"no wait delay",
|
||||||
"no wait expression",
|
"no wait expression",
|
||||||
|
"set device metrics override",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "success (clip)",
|
||||||
|
browser: newChromiumBrowser(
|
||||||
|
browserArguments{
|
||||||
|
binPath: os.Getenv("CHROMIUM_BIN_PATH"),
|
||||||
|
wsUrlReadTimeout: 5 * time.Second,
|
||||||
|
allowList: regexp2.MustCompile("", 0),
|
||||||
|
denyList: regexp2.MustCompile("", 0),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fs: func() *gotenberg.FileSystem {
|
||||||
|
fs := gotenberg.NewFileSystem()
|
||||||
|
|
||||||
|
err := os.MkdirAll(fs.WorkingDirPath(), 0o755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf(fmt.Sprintf("expected no error but got: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(fmt.Sprintf("%s/index.html", fs.WorkingDirPath()), []byte("<h1>Default options</h1>"), 0o755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs
|
||||||
|
}(),
|
||||||
|
options: func() ScreenshotOptions {
|
||||||
|
options := DefaultScreenshotOptions()
|
||||||
|
options.Clip = true
|
||||||
|
return options
|
||||||
|
}(),
|
||||||
|
noDeadline: false,
|
||||||
|
start: true,
|
||||||
|
expectError: false,
|
||||||
|
expectedLogEntries: []string{
|
||||||
|
"cache not cleared",
|
||||||
|
"cookies not cleared",
|
||||||
|
"JavaScript not disabled",
|
||||||
|
"no cookies to set",
|
||||||
|
"no extra HTTP headers",
|
||||||
|
"navigate to",
|
||||||
|
"default white background not hidden",
|
||||||
|
"no emulated media type",
|
||||||
|
"no wait delay",
|
||||||
|
"no wait expression",
|
||||||
|
"set device metrics override",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2042,6 +2090,7 @@ func TestChromiumBrowser_screenshot(t *testing.T) {
|
|||||||
"no emulated media type",
|
"no emulated media type",
|
||||||
"no wait delay",
|
"no wait delay",
|
||||||
"no wait expression",
|
"no wait expression",
|
||||||
|
"set device metrics override",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
|||||||
@@ -239,6 +239,19 @@ func DefaultPdfOptions() PdfOptions {
|
|||||||
type ScreenshotOptions struct {
|
type ScreenshotOptions struct {
|
||||||
Options
|
Options
|
||||||
|
|
||||||
|
// Width is the device screen width in pixels.
|
||||||
|
// Optional.
|
||||||
|
Width int
|
||||||
|
|
||||||
|
// Height is the device screen height in pixels.
|
||||||
|
// Optional.
|
||||||
|
Height int
|
||||||
|
|
||||||
|
// Clip defines whether to clip the screenshot according to the device
|
||||||
|
// dimensions.
|
||||||
|
// Optional.
|
||||||
|
Clip bool
|
||||||
|
|
||||||
// Format is the image compression format, either "png" or "jpeg" or
|
// Format is the image compression format, either "png" or "jpeg" or
|
||||||
// "webp".
|
// "webp".
|
||||||
// Optional.
|
// Optional.
|
||||||
@@ -258,6 +271,9 @@ type ScreenshotOptions struct {
|
|||||||
func DefaultScreenshotOptions() ScreenshotOptions {
|
func DefaultScreenshotOptions() ScreenshotOptions {
|
||||||
return ScreenshotOptions{
|
return ScreenshotOptions{
|
||||||
Options: DefaultOptions(),
|
Options: DefaultOptions(),
|
||||||
|
Width: 800,
|
||||||
|
Height: 600,
|
||||||
|
Clip: false,
|
||||||
Format: "png",
|
Format: "png",
|
||||||
Quality: 100,
|
Quality: 100,
|
||||||
OptimizeForSpeed: false,
|
OptimizeForSpeed: false,
|
||||||
|
|||||||
@@ -182,12 +182,17 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
|
|||||||
defaultScreenshotOptions := DefaultScreenshotOptions()
|
defaultScreenshotOptions := DefaultScreenshotOptions()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
width, height int
|
||||||
|
clip bool
|
||||||
format string
|
format string
|
||||||
quality int
|
quality int
|
||||||
optimizeForSpeed bool
|
optimizeForSpeed bool
|
||||||
)
|
)
|
||||||
|
|
||||||
form.
|
form.
|
||||||
|
Int("width", &width, defaultScreenshotOptions.Width).
|
||||||
|
Int("height", &height, defaultScreenshotOptions.Height).
|
||||||
|
Bool("clip", &clip, defaultScreenshotOptions.Clip).
|
||||||
Custom("format", func(value string) error {
|
Custom("format", func(value string) error {
|
||||||
if value == "" {
|
if value == "" {
|
||||||
format = defaultScreenshotOptions.Format
|
format = defaultScreenshotOptions.Format
|
||||||
@@ -228,6 +233,9 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
|
|||||||
|
|
||||||
screenshotOptions := ScreenshotOptions{
|
screenshotOptions := ScreenshotOptions{
|
||||||
Options: options,
|
Options: options,
|
||||||
|
Width: width,
|
||||||
|
Height: height,
|
||||||
|
Clip: clip,
|
||||||
Format: format,
|
Format: format,
|
||||||
Quality: quality,
|
Quality: quality,
|
||||||
OptimizeForSpeed: optimizeForSpeed,
|
OptimizeForSpeed: optimizeForSpeed,
|
||||||
|
|||||||
@@ -385,6 +385,15 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
|
|||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
ctx.SetValues(map[string][]string{
|
ctx.SetValues(map[string][]string{
|
||||||
|
"width": {
|
||||||
|
"1280",
|
||||||
|
},
|
||||||
|
"height": {
|
||||||
|
"800",
|
||||||
|
},
|
||||||
|
"clip": {
|
||||||
|
"true",
|
||||||
|
},
|
||||||
"optimizeForSpeed": {
|
"optimizeForSpeed": {
|
||||||
"true",
|
"true",
|
||||||
},
|
},
|
||||||
@@ -396,6 +405,9 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
|
|||||||
}(),
|
}(),
|
||||||
expectedOptions: func() ScreenshotOptions {
|
expectedOptions: func() ScreenshotOptions {
|
||||||
options := DefaultScreenshotOptions()
|
options := DefaultScreenshotOptions()
|
||||||
|
options.Width = 1280
|
||||||
|
options.Height = 800
|
||||||
|
options.Clip = true
|
||||||
options.OptimizeForSpeed = true
|
options.OptimizeForSpeed = true
|
||||||
options.EmulatedMediaType = "screen"
|
options.EmulatedMediaType = "screen"
|
||||||
return options
|
return options
|
||||||
|
|||||||
@@ -121,6 +121,14 @@ func captureScreenshotActionFunc(logger *zap.Logger, outputPath string, options
|
|||||||
WithOptimizeForSpeed(options.OptimizeForSpeed).
|
WithOptimizeForSpeed(options.OptimizeForSpeed).
|
||||||
WithFormat(page.CaptureScreenshotFormat(options.Format))
|
WithFormat(page.CaptureScreenshotFormat(options.Format))
|
||||||
|
|
||||||
|
if options.Clip {
|
||||||
|
captureScreenshot = captureScreenshot.WithClip(&page.Viewport{
|
||||||
|
Width: float64(options.Width),
|
||||||
|
Height: float64(options.Height),
|
||||||
|
Scale: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if options.Format == "jpeg" {
|
if options.Format == "jpeg" {
|
||||||
captureScreenshot = captureScreenshot.
|
captureScreenshot = captureScreenshot.
|
||||||
WithQuality(int64(options.Quality))
|
WithQuality(int64(options.Quality))
|
||||||
@@ -154,6 +162,19 @@ func captureScreenshotActionFunc(logger *zap.Logger, outputPath string, options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setDeviceMetricsOverride(logger *zap.Logger, width, height int) chromedp.ActionFunc {
|
||||||
|
return func(ctx context.Context) error {
|
||||||
|
logger.Debug("set device metrics override")
|
||||||
|
|
||||||
|
err := emulation.SetDeviceMetricsOverride(int64(width), int64(height), 1.0, false).Do(ctx)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("set device metrics override: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func clearCacheActionFunc(logger *zap.Logger, clear bool) chromedp.ActionFunc {
|
func clearCacheActionFunc(logger *zap.Logger, clear bool) chromedp.ActionFunc {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
// See https://github.com/gotenberg/gotenberg/issues/753.
|
// See https://github.com/gotenberg/gotenberg/issues/753.
|
||||||
|
|||||||
Reference in New Issue
Block a user