From 352c09d292775fa66543a3d29f09590f2b5fd092 Mon Sep 17 00:00:00 2001 From: CanadaHonk Date: Sun, 29 Jan 2023 19:22:36 +0000 Subject: [PATCH] api/page: add printToPDF --- gluon.d.ts | 122 +++++++++++++++++++++++++++++++++++++++++ src/launcher/inject.js | 22 ++++++++ 2 files changed, 144 insertions(+) diff --git a/gluon.d.ts b/gluon.d.ts index f2d8a35..1c26bfc 100644 --- a/gluon.d.ts +++ b/gluon.d.ts @@ -53,6 +53,107 @@ type V8CacheApi = { ): Promise }; +type PrintToPDFOptions = { + /** + * Paper orientation. + * @default false + */ + landscape?: boolean, + + /** + * Display header and footer. + * @default false + */ + displayHeaderFooter?: boolean, + + /** + * Print background graphics. + * @default false + */ + printBackground?: boolean, + + /** + * Scale of the webpage rendering. + * @default 1 + */ + scale?: number, + + /** + * Paper width in inches. + * @default 8.5 + */ + paperWidth?: number, + + /** + * Paper height in inches. + * @default 11 + */ + paperHeight?: number, + + /** + * Top margin in inches. + * @default 0.4 + */ + marginTop?: number, + + /** + * Bottom margin in inches. + * @default 0.4 + */ + marginBottom?: number, + + /** + * Left margin in inches. + * @default 0.4 + */ + marginLeft?: number, + + /** + * Right margin in inches. + * @default 0.4 + */ + marginRight?: number, + + /** + * Paper ranges to print, one based, (eg '1-5, 8, 11-13'). + * Pages are printed in the document order, not in the order specified, and no more than once. + * Defaults to an empty string, which implies all pages available are printed. + * @default '' + */ + pageRanges?: string, + + /** + * HTML template for the print header. + * You can use the following classes which will have the relevant print data injected into the contents: + * - `date` - formatted print date + * - `title` - document title + * - `url` - document location + * - `pageNumber` - current page number + * - `totalPages` - total pages in the document + * @example `` would create a span containing the document title. + */ + headerTemplate?: string, + + /** + * HTML template for the print footer. + * You can use the following classes which will have the relevant print data injected into the contents: + * - `date` - formatted print date + * - `title` - document title + * - `url` - document location + * - `pageNumber` - current page number + * - `totalPages` - total pages in the document + * @example `` would create a span containing the document title. + */ + footerTemplate?: string, + + /** + * Prefer the page size defined by the page's CSS. + * When set to false, it will scale to fit the paper size. + * @default false + */ + preferCSSPageSize?: boolean, +}; + type PageApi = { /** * Evaluate a string or function in the web context. @@ -85,6 +186,27 @@ type PageApi = { */ ignoreCache?: boolean ): Promise, + + /** + * Print (save) the page as a PDF, optionally to a file. + * @returns Buffer of PDF data. + */ + printToPDF( + /** Optional print options (based on Chromium's headless standard). */ + options?: PrintToPDFOptions + ): Promise, + + /** + * Print (save) the page as a PDF to a file. + * @returns Buffer of PDF data. + */ + printToPDF( + /** Path to save the PDF to. Do not include to just get a Buffer. */ + path: string, + + /** Optional print options (based on Chromium's headless standard). */ + options?: PrintToPDFOptions + ): Promise }; type IPCStoreApi = { diff --git a/src/launcher/inject.js b/src/launcher/inject.js index a3717b3..6b431fb 100644 --- a/src/launcher/inject.js +++ b/src/launcher/inject.js @@ -1,3 +1,4 @@ +import { writeFile } from 'fs/promises'; import { log } from '../lib/logger.js'; import IPCApi from '../lib/ipc.js'; @@ -114,6 +115,27 @@ export default async (CDP, proc, injectionType = 'browser', { dataPath, browserN await Window.cdp.send('Page.reload', { ignoreCache }); + }, + + printToPDF: async (...args) => { + let path, options; + + if (args.length === 1) { + if (typeof args[0] === 'string') path = args[0]; + else options = args[0]; + } + + if (args.length === 2) { + [ path, options ] = args; + } + + + const { data } = await CDP.send('Page.printToPDF', options); + const buffer = Buffer.from(data, 'base64'); + + if (path) await writeFile(path, buffer); + + return buffer; } },