Implement printing to PDF

This patch implements:
- puppeteer's Page.printToPDF method. The method's defaults
  are similar to phantom's defaults for the paperSize property.
- phantom's render into pdf file.
This commit is contained in:
Andrey Lushnikov 2017-05-14 11:29:42 -07:00
parent 72ce46c4f6
commit 91e54378a3
2 changed files with 113 additions and 1 deletions

View File

@ -386,6 +386,54 @@ class Page extends EventEmitter {
fs.writeFileSync(filePath, buffer);
}
/**
* @param {string} filePath
* @param {!Object=} options
*/
async printToPDF(filePath, options) {
options = options || {};
var scale = options.scale || 1;
var displayHeaderFooter = options.displayHeaderFooter || false;
var printBackground = options.printBackground || true;
var landscape = options.landscape || false;
var pageRanges = options.pageRanges || '';
var paperWidth = 8.5;
var paperHeight = 11;
if (options.format) {
var format = Page.PaperFormats[options.format];
console.assert(format, 'Unknown paper format: ' + options.format);
paperWidth = format.width;
paperHeight = format.height;
} else {
paperWidth = convertPrintParameterToInches(options.width) || paperWidth;
paperHeight = convertPrintParameterToInches(options.height) || paperHeight;
}
var marginOptions = options.margin || {};
var marginTop = convertPrintParameterToInches(marginOptions.top) || 0;
var marginLeft = convertPrintParameterToInches(marginOptions.left) || 0;
var marginBottom = convertPrintParameterToInches(marginOptions.bottom) || 0;
var marginRight = convertPrintParameterToInches(marginOptions.right) || 0;
var result = await this._client.send('Page.printToPDF', {
landscape: landscape,
displayHeaderFooter: displayHeaderFooter,
printBackground: printBackground,
scale: scale,
paperWidth: paperWidth,
paperHeight: paperHeight,
marginTop: marginTop,
marginBottom: marginBottom,
marginLeft: marginLeft,
marginRight: marginRight,
pageRanges: pageRanges
});
var buffer = new Buffer(result.data, 'base64');
fs.writeFileSync(filePath, buffer);
}
/**
* @return {!Promise<string>}
*/
@ -429,6 +477,59 @@ Page.ScreenshotTypes = {
JPG: "jpeg",
};
/** @enum {string} */
Page.PaperFormats = {
Letter: {width: 8.5, height: 11},
Legal: {width: 8.5, height: 14},
Tabloid: {width: 11, height: 17},
Ledger: {width: 17, height: 11},
A0: {width: 33.1, height: 46.8 },
A1: {width: 23.4, height: 33.1 },
A2: {width: 16.5, height: 23.4 },
A3: {width: 11.7, height: 16.5 },
A4: {width: 8.27, height: 11.7 },
A5: {width: 5.83, height: 8.27 },
};
var unitToPixels = {
'px': 1,
'in': 96,
'cm': 37.8,
'mm': 3.78
};
/**
* @param {(string|number|undefined)} parameter
* @return {(number|undefined)}
*/
function convertPrintParameterToInches(parameter) {
if (typeof parameter === 'undefined')
return undefined;
var pixels;
if (typeof parameter === 'number') {
// Treat numbers as pixel values to be aligned with phantom's paperSize.
pixels = /** @type {number} */ (parameter);
} else if (typeof parameter === 'string') {
var text = parameter;
var unit = text.substring(text.length - 2).toLowerCase();
var valueText = '';
if (unitToPixels.hasOwnProperty(unit)) {
valueText = text.substring(0, text.length - 2);
} else {
// In case of unknown unit try to parse the whole parameter as number of pixels.
// This is consistent with phantom's paperSize behavior.
unit = 'px';
valueText = text;
}
var value = Number(valueText);
console.assert(!isNaN(value), 'Failed to parse parameter value: ' + text);
var pixels = value * unitToPixels[unit];
} else {
throw new Error('printToPDF Cannot handle parameter type: ' + (typeof parameter));
}
return pixels / 96;
};
Page.Events = {
Alert: 'alert',
BeforeUnload: 'beforeunload',

View File

@ -276,7 +276,18 @@ class WebPage {
height: this.clipRect.height
};
}
var imageBuffer = await(this._page.saveScreenshot(fileName, clipRect));
if (fileName.endsWith('pdf')) {
var options = {};
var paperSize = this.paperSize || {};
options.margin = paperSize.margin;
options.format = paperSize.format;
options.landscape = paperSize.orientation === 'landscape';
options.width = paperSize.width;
options.height = paperSize.height;
await(this._page.printToPDF(fileName, options));
} else {
await(this._page.saveScreenshot(fileName, clipRect));
}
}
release() {