Skip to content

Commit

Permalink
feat(chromium): add clip options to screenshot routes
Browse files Browse the repository at this point in the history
  • Loading branch information
gulien committed Apr 25, 2024
1 parent a890968 commit 0f0a6ce
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkg/modules/chromium/browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ func (b *chromiumBrowser) screenshot(ctx context.Context, logger *zap.Logger, ur
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
// Screenshot specific.
setDeviceMetricsOverride(logger, options.Width, options.Height),
captureScreenshotActionFunc(logger, outputPath, options),
})
}
Expand Down
49 changes: 49 additions & 0 deletions pkg/modules/chromium/browser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1996,6 +1996,54 @@ func TestChromiumBrowser_screenshot(t *testing.T) {
"no emulated media type",
"no wait delay",
"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",
},
},
{
Expand Down Expand Up @@ -2042,6 +2090,7 @@ func TestChromiumBrowser_screenshot(t *testing.T) {
"no emulated media type",
"no wait delay",
"no wait expression",
"set device metrics override",
},
},
} {
Expand Down
16 changes: 16 additions & 0 deletions pkg/modules/chromium/chromium.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,19 @@ func DefaultPdfOptions() PdfOptions {
type ScreenshotOptions struct {
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
// "webp".
// Optional.
Expand All @@ -258,6 +271,9 @@ type ScreenshotOptions struct {
func DefaultScreenshotOptions() ScreenshotOptions {
return ScreenshotOptions{
Options: DefaultOptions(),
Width: 800,
Height: 600,
Clip: false,
Format: "png",
Quality: 100,
OptimizeForSpeed: false,
Expand Down
8 changes: 8 additions & 0 deletions pkg/modules/chromium/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,17 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
defaultScreenshotOptions := DefaultScreenshotOptions()

var (
width, height int
clip bool
format string
quality int
optimizeForSpeed bool
)

form.
Int("width", &width, defaultScreenshotOptions.Width).
Int("height", &height, defaultScreenshotOptions.Height).
Bool("clip", &clip, defaultScreenshotOptions.Clip).
Custom("format", func(value string) error {
if value == "" {
format = defaultScreenshotOptions.Format
Expand Down Expand Up @@ -228,6 +233,9 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens

screenshotOptions := ScreenshotOptions{
Options: options,
Width: width,
Height: height,
Clip: clip,
Format: format,
Quality: quality,
OptimizeForSpeed: optimizeForSpeed,
Expand Down
12 changes: 12 additions & 0 deletions pkg/modules/chromium/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,15 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
ctx: func() *api.ContextMock {
ctx := &api.ContextMock{Context: new(api.Context)}
ctx.SetValues(map[string][]string{
"width": {
"1280",
},
"height": {
"800",
},
"clip": {
"true",
},
"optimizeForSpeed": {
"true",
},
Expand All @@ -396,6 +405,9 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
}(),
expectedOptions: func() ScreenshotOptions {
options := DefaultScreenshotOptions()
options.Width = 1280
options.Height = 800
options.Clip = true
options.OptimizeForSpeed = true
options.EmulatedMediaType = "screen"
return options
Expand Down
21 changes: 21 additions & 0 deletions pkg/modules/chromium/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ func captureScreenshotActionFunc(logger *zap.Logger, outputPath string, options
WithOptimizeForSpeed(options.OptimizeForSpeed).
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" {
captureScreenshot = captureScreenshot.
WithQuality(int64(options.Quality))
Expand Down Expand Up @@ -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 {
return func(ctx context.Context) error {
// See https://github.com/gotenberg/gotenberg/issues/753.
Expand Down

0 comments on commit 0f0a6ce

Please sign in to comment.