diff --git a/pkg/modules/chromium/browser_test.go b/pkg/modules/chromium/browser_test.go
index 4a4bc540..b33b5ae3 100644
--- a/pkg/modules/chromium/browser_test.go
+++ b/pkg/modules/chromium/browser_test.go
@@ -950,6 +950,41 @@ func TestChromiumBrowser_pdf(t *testing.T) {
"wait until 'window.globalVar === 'ready'' is true before print",
},
},
+ {
+ scenario: "single page",
+ 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("
Custom header and footer
"), 0o755)
+ if err != nil {
+ t.Fatalf("expected no error but got: %v", err)
+ }
+
+ return fs
+ }(),
+ options: PdfOptions{
+ SinglePage: true,
+ },
+ noDeadline: false,
+ start: true,
+ expectError: false,
+ expectedLogEntries: []string{
+ "single page PDF",
+ },
+ },
{
scenario: "custom header and footer",
browser: newChromiumBrowser(
diff --git a/pkg/modules/chromium/chromium.go b/pkg/modules/chromium/chromium.go
index 9a3594ea..0ab4ad36 100644
--- a/pkg/modules/chromium/chromium.go
+++ b/pkg/modules/chromium/chromium.go
@@ -150,6 +150,11 @@ type PdfOptions struct {
// Optional.
Scale float64
+ // SinglePage defines whether to print the entire content in one single
+ // page.
+ // Optional.
+ SinglePage bool
+
// PaperWidth is the paper width, in inches.
// Optional.
PaperWidth float64
@@ -209,6 +214,7 @@ func DefaultPdfOptions() PdfOptions {
Landscape: false,
PrintBackground: false,
Scale: 1.0,
+ SinglePage: false,
PaperWidth: 8.5,
PaperHeight: 11,
MarginTop: 0.39,
diff --git a/pkg/modules/chromium/routes.go b/pkg/modules/chromium/routes.go
index e43400a7..f490963c 100644
--- a/pkg/modules/chromium/routes.go
+++ b/pkg/modules/chromium/routes.go
@@ -109,7 +109,7 @@ func FormDataChromiumPdfOptions(ctx *api.Context) (*api.FormData, PdfOptions) {
defaultPdfOptions := DefaultPdfOptions()
var (
- landscape, printBackground bool
+ landscape, printBackground, singlePage bool
scale, paperWidth, paperHeight float64
marginTop, marginBottom, marginLeft, marginRight float64
pageRanges string
@@ -121,6 +121,7 @@ func FormDataChromiumPdfOptions(ctx *api.Context) (*api.FormData, PdfOptions) {
Bool("landscape", &landscape, defaultPdfOptions.Landscape).
Bool("printBackground", &printBackground, defaultPdfOptions.PrintBackground).
Float64("scale", &scale, defaultPdfOptions.Scale).
+ Bool("singlePage", &singlePage, defaultPdfOptions.SinglePage).
Float64("paperWidth", &paperWidth, defaultPdfOptions.PaperWidth).
Float64("paperHeight", &paperHeight, defaultPdfOptions.PaperHeight).
Float64("marginTop", &marginTop, defaultPdfOptions.MarginTop).
@@ -137,6 +138,7 @@ func FormDataChromiumPdfOptions(ctx *api.Context) (*api.FormData, PdfOptions) {
Landscape: landscape,
PrintBackground: printBackground,
Scale: scale,
+ SinglePage: singlePage,
PaperWidth: paperWidth,
PaperHeight: paperHeight,
MarginTop: marginTop,
diff --git a/pkg/modules/chromium/tasks.go b/pkg/modules/chromium/tasks.go
index d77688b6..76068dd1 100644
--- a/pkg/modules/chromium/tasks.go
+++ b/pkg/modules/chromium/tasks.go
@@ -17,19 +17,37 @@ import (
func printToPdfActionFunc(logger *zap.Logger, outputPath string, options PdfOptions) chromedp.ActionFunc {
return func(ctx context.Context) error {
+ paperHeight := options.PaperHeight
+ pageRanges := options.PageRanges
+
+ if options.SinglePage {
+ logger.Debug("single page PDF")
+
+ _, _, _, _, _, cssContentSize, err := page.GetLayoutMetrics().Do(ctx)
+ if err != nil {
+ return fmt.Errorf("get layout metrics: %w", err)
+ }
+
+ // There are 96 CSS pixels per inch.
+ // See https://issues.chromium.org/issues/40267771#comment14.
+ paperHeight = cssContentSize.Height / 96
+ pageRanges = "1" // little dirty hack to avoid leftovers.
+ }
+
printToPdf := page.PrintToPDF().
WithTransferMode(page.PrintToPDFTransferModeReturnAsStream).
WithLandscape(options.Landscape).
WithPrintBackground(options.PrintBackground).
WithScale(options.Scale).
WithPaperWidth(options.PaperWidth).
- WithPaperHeight(options.PaperHeight).
+ WithPaperHeight(paperHeight).
WithMarginTop(options.MarginTop).
WithMarginBottom(options.MarginBottom).
WithMarginLeft(options.MarginLeft).
WithMarginRight(options.MarginRight).
- WithPageRanges(options.PageRanges).
- WithPreferCSSPageSize(options.PreferCssPageSize)
+ WithPageRanges(pageRanges).
+ WithPreferCSSPageSize(options.PreferCssPageSize).
+ WithGenerateTaggedPDF(true)
hasCustomHeaderFooter := options.HeaderTemplate != DefaultPdfOptions().HeaderTemplate ||
options.FooterTemplate != DefaultPdfOptions().FooterTemplate