Skip to content

Commit

Permalink
refactor: options parsing in WebContents.prototype.printToPDF() (#40257)
Browse files Browse the repository at this point in the history
* refactor: options parsing in WebContents.prototype.printToPDF()

* tweak parsePageSize
  • Loading branch information
miniak committed Oct 19, 2023
1 parent 025af35 commit beb0cbc
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 137 deletions.
176 changes: 42 additions & 134 deletions lib/browser/api/web-contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,148 +187,56 @@ WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (worldId
return ipcMainUtils.invokeInWebContents(this, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, 'executeJavaScriptInIsolatedWorld', worldId, code, !!hasUserGesture);
};

// Translate the options of printToPDF.

let pendingPromise: Promise<any> | undefined;
WebContents.prototype.printToPDF = async function (options) {
const printSettings: Record<string, any> = {
requestID: getNextId(),
landscape: false,
displayHeaderFooter: false,
headerTemplate: '',
footerTemplate: '',
printBackground: false,
scale: 1.0,
paperWidth: 8.5,
paperHeight: 11.0,
marginTop: 0.4,
marginBottom: 0.4,
marginLeft: 0.4,
marginRight: 0.4,
pageRanges: '',
preferCSSPageSize: false,
shouldGenerateTaggedPDF: false
};

if (options.landscape !== undefined) {
if (typeof options.landscape !== 'boolean') {
throw new Error('landscape must be a Boolean');
}
printSettings.landscape = options.landscape;
}

if (options.displayHeaderFooter !== undefined) {
if (typeof options.displayHeaderFooter !== 'boolean') {
throw new Error('displayHeaderFooter must be a Boolean');
}
printSettings.displayHeaderFooter = options.displayHeaderFooter;
}

if (options.printBackground !== undefined) {
if (typeof options.printBackground !== 'boolean') {
throw new Error('printBackground must be a Boolean');
}
printSettings.shouldPrintBackgrounds = options.printBackground;
function checkType<T> (value: T, type: 'number' | 'boolean' | 'string' | 'object', name: string): T {
// eslint-disable-next-line valid-typeof
if (typeof value !== type) {
throw new TypeError(`${name} must be a ${type}`);
}

if (options.scale !== undefined) {
if (typeof options.scale !== 'number') {
throw new Error('scale must be a Number');
}
printSettings.scale = options.scale;
}

const { pageSize } = options;
if (pageSize !== undefined) {
if (typeof pageSize === 'string') {
const format = paperFormats[pageSize.toLowerCase()];
if (!format) {
throw new Error(`Invalid pageSize ${pageSize}`);
}

printSettings.paperWidth = format.width;
printSettings.paperHeight = format.height;
} else if (typeof options.pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
throw new Error('height and width properties are required for pageSize');
}

printSettings.paperWidth = pageSize.width;
printSettings.paperHeight = pageSize.height;
} else {
throw new Error('pageSize must be a String or Object');
}
}

const { margins } = options;
if (margins !== undefined) {
if (typeof margins !== 'object') {
throw new Error('margins must be an Object');
}

if (margins.top !== undefined) {
if (typeof margins.top !== 'number') {
throw new Error('margins.top must be a Number');
}
printSettings.marginTop = margins.top;
}

if (margins.bottom !== undefined) {
if (typeof margins.bottom !== 'number') {
throw new Error('margins.bottom must be a Number');
}
printSettings.marginBottom = margins.bottom;
}

if (margins.left !== undefined) {
if (typeof margins.left !== 'number') {
throw new Error('margins.left must be a Number');
}
printSettings.marginLeft = margins.left;
}
return value;
}

if (margins.right !== undefined) {
if (typeof margins.right !== 'number') {
throw new Error('margins.right must be a Number');
}
printSettings.marginRight = margins.right;
function parsePageSize (pageSize: string | ElectronInternal.PageSize) {
if (typeof pageSize === 'string') {
const format = paperFormats[pageSize.toLowerCase()];
if (!format) {
throw new Error(`Invalid pageSize ${pageSize}`);
}
}

if (options.pageRanges !== undefined) {
if (typeof options.pageRanges !== 'string') {
throw new Error('pageRanges must be a String');
return { paperWidth: format.width, paperHeight: format.height };
} else if (typeof pageSize === 'object') {
if (typeof pageSize.width !== 'number' || typeof pageSize.height !== 'number') {
throw new TypeError('width and height properties are required for pageSize');
}
printSettings.pageRanges = options.pageRanges;
}

if (options.headerTemplate !== undefined) {
if (typeof options.headerTemplate !== 'string') {
throw new Error('headerTemplate must be a String');
}
printSettings.headerTemplate = options.headerTemplate;
}

if (options.footerTemplate !== undefined) {
if (typeof options.footerTemplate !== 'string') {
throw new Error('footerTemplate must be a String');
}
printSettings.footerTemplate = options.footerTemplate;
return { paperWidth: pageSize.width, paperHeight: pageSize.height };
} else {
throw new TypeError('pageSize must be a string or an object');
}
}

if (options.preferCSSPageSize !== undefined) {
if (typeof options.preferCSSPageSize !== 'boolean') {
throw new Error('preferCSSPageSize must be a Boolean');
}
printSettings.preferCSSPageSize = options.preferCSSPageSize;
}
// Translate the options of printToPDF.

if (options.generateTaggedPDF !== undefined) {
if (typeof options.generateTaggedPDF !== 'boolean') {
throw new Error('generateTaggedPDF must be a Boolean');
}
printSettings.shouldGenerateTaggedPDF = options.generateTaggedPDF;
}
let pendingPromise: Promise<any> | undefined;
WebContents.prototype.printToPDF = async function (options) {
const margins = checkType(options.margins ?? {}, 'object', 'margins');
const printSettings = {
requestID: getNextId(),
landscape: checkType(options.landscape ?? false, 'boolean', 'landscape'),
displayHeaderFooter: checkType(options.displayHeaderFooter ?? false, 'boolean', 'displayHeaderFooter'),
headerTemplate: checkType(options.headerTemplate ?? '', 'string', 'headerTemplate'),
footerTemplate: checkType(options.footerTemplate ?? '', 'string', 'footerTemplate'),
printBackground: checkType(options.printBackground ?? false, 'boolean', 'printBackground'),
scale: checkType(options.scale ?? 1.0, 'number', 'scale'),
marginTop: checkType(margins.top ?? 0.4, 'number', 'margins.top'),
marginBottom: checkType(margins.bottom ?? 0.4, 'number', 'margins.bottom'),
marginLeft: checkType(margins.left ?? 0.4, 'number', 'margins.left'),
marginRight: checkType(margins.right ?? 0.4, 'number', 'margins.right'),
pageRanges: checkType(options.pageRanges ?? '', 'string', 'pageRanges'),
preferCSSPageSize: checkType(options.preferCSSPageSize ?? false, 'boolean', 'preferCSSPageSize'),
generateTaggedPDF: checkType(options.generateTaggedPDF ?? false, 'boolean', 'generateTaggedPDF'),
...parsePageSize(options.pageSize ?? 'letter')
};

if (this._printToPDF) {
if (pendingPromise) {
Expand All @@ -346,7 +254,7 @@ WebContents.prototype.printToPDF = async function (options) {
// print param logic into new file shared between printToPDF and print
WebContents.prototype.print = function (options: ElectronInternal.WebContentsPrintOptions, callback) {
if (typeof options !== 'object') {
throw new Error('webContents.print(): Invalid print settings specified.');
throw new TypeError('webContents.print(): Invalid print settings specified.');
}

const printSettings: Record<string, any> = { ...options };
Expand All @@ -361,7 +269,7 @@ WebContents.prototype.print = function (options: ElectronInternal.WebContentsPri
const height = Math.ceil(pageSize.height);
const width = Math.ceil(pageSize.width);
if (!isValidCustomPageSize(width, height)) {
throw new Error('height and width properties must be minimum 352 microns.');
throw new RangeError('height and width properties must be minimum 352 microns.');
}

printSettings.mediaSize = {
Expand Down
3 changes: 1 addition & 2 deletions shell/browser/api/electron_api_web_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3116,8 +3116,7 @@ v8::Local<v8::Promise> WebContents::PrintToPDF(const base::Value& settings) {
auto header_template = *settings.GetDict().FindString("headerTemplate");
auto footer_template = *settings.GetDict().FindString("footerTemplate");
auto prefer_css_page_size = settings.GetDict().FindBool("preferCSSPageSize");
auto generate_tagged_pdf =
settings.GetDict().FindBool("shouldGenerateTaggedPDF");
auto generate_tagged_pdf = settings.GetDict().FindBool("generateTaggedPDF");

absl::variant<printing::mojom::PrintPagesParamsPtr, std::string>
print_pages_params = print_to_pdf::GetPrintPagesParams(
Expand Down
6 changes: 5 additions & 1 deletion spec/ts-smoke/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ app.whenReady().then(() => {
},
printBackground: true,
pageRanges: '1-3',
landscape: true
landscape: true,
pageSize: {
width: 100,
height: 100
}
}).then((data: Buffer) => console.log(data));

mainWindow.webContents.printToPDF({}).then(data => console.log(data));
Expand Down

0 comments on commit beb0cbc

Please sign in to comment.