mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
refactor: move PDF options to utilities (#11651)
This commit is contained in:
parent
cf16cb49c9
commit
27dd2fc8ca
@ -47,12 +47,7 @@ import {
|
||||
} from '../common/EventEmitter.js';
|
||||
import type {FileChooser} from '../common/FileChooser.js';
|
||||
import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js';
|
||||
import {
|
||||
paperFormats,
|
||||
type LowerCasePaperFormat,
|
||||
type ParsedPDFOptions,
|
||||
type PDFOptions,
|
||||
} from '../common/PDFOptions.js';
|
||||
import type {PDFOptions} from '../common/PDFOptions.js';
|
||||
import {TimeoutSettings} from '../common/TimeoutSettings.js';
|
||||
import type {
|
||||
Awaitable,
|
||||
@ -64,14 +59,12 @@ import type {
|
||||
import {
|
||||
debugError,
|
||||
importFSPromises,
|
||||
isNumber,
|
||||
isString,
|
||||
timeout,
|
||||
withSourcePuppeteerURLIfNone,
|
||||
} from '../common/util.js';
|
||||
import type {Viewport} from '../common/Viewport.js';
|
||||
import type {ScreenRecorder} from '../node/ScreenRecorder.js';
|
||||
import {assert} from '../util/assert.js';
|
||||
import {guarded} from '../util/decorators.js';
|
||||
import {
|
||||
AsyncDisposableStack,
|
||||
@ -2499,60 +2492,6 @@ export abstract class Page extends EventEmitter<PageEvents> {
|
||||
*/
|
||||
abstract _screenshot(options: Readonly<ScreenshotOptions>): Promise<string>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_getPDFOptions(
|
||||
options: PDFOptions = {},
|
||||
lengthUnit: 'in' | 'cm' = 'in'
|
||||
): ParsedPDFOptions {
|
||||
const defaults: Omit<ParsedPDFOptions, 'width' | 'height' | 'margin'> = {
|
||||
scale: 1,
|
||||
displayHeaderFooter: false,
|
||||
headerTemplate: '',
|
||||
footerTemplate: '',
|
||||
printBackground: false,
|
||||
landscape: false,
|
||||
pageRanges: '',
|
||||
preferCSSPageSize: false,
|
||||
omitBackground: false,
|
||||
timeout: 30000,
|
||||
tagged: false,
|
||||
};
|
||||
|
||||
let width = 8.5;
|
||||
let height = 11;
|
||||
if (options.format) {
|
||||
const format =
|
||||
paperFormats[options.format.toLowerCase() as LowerCasePaperFormat];
|
||||
assert(format, 'Unknown paper format: ' + options.format);
|
||||
width = format.width;
|
||||
height = format.height;
|
||||
} else {
|
||||
width = convertPrintParameterToInches(options.width, lengthUnit) ?? width;
|
||||
height =
|
||||
convertPrintParameterToInches(options.height, lengthUnit) ?? height;
|
||||
}
|
||||
|
||||
const margin = {
|
||||
top: convertPrintParameterToInches(options.margin?.top, lengthUnit) || 0,
|
||||
left:
|
||||
convertPrintParameterToInches(options.margin?.left, lengthUnit) || 0,
|
||||
bottom:
|
||||
convertPrintParameterToInches(options.margin?.bottom, lengthUnit) || 0,
|
||||
right:
|
||||
convertPrintParameterToInches(options.margin?.right, lengthUnit) || 0,
|
||||
};
|
||||
|
||||
return {
|
||||
...defaults,
|
||||
...options,
|
||||
width,
|
||||
height,
|
||||
margin,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a PDF of the page with the `print` CSS media type.
|
||||
*
|
||||
@ -3017,50 +2956,6 @@ export const supportedMetrics = new Set<string>([
|
||||
'JSHeapTotalSize',
|
||||
]);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const unitToPixels = {
|
||||
px: 1,
|
||||
in: 96,
|
||||
cm: 37.8,
|
||||
mm: 3.78,
|
||||
};
|
||||
|
||||
function convertPrintParameterToInches(
|
||||
parameter?: string | number,
|
||||
lengthUnit: 'in' | 'cm' = 'in'
|
||||
): number | undefined {
|
||||
if (typeof parameter === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
let pixels;
|
||||
if (isNumber(parameter)) {
|
||||
// Treat numbers as pixel values to be aligned with phantom's paperSize.
|
||||
pixels = parameter;
|
||||
} else if (isString(parameter)) {
|
||||
const text = parameter;
|
||||
let unit = text.substring(text.length - 2).toLowerCase();
|
||||
let valueText = '';
|
||||
if (unit in unitToPixels) {
|
||||
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;
|
||||
}
|
||||
const value = Number(valueText);
|
||||
assert(!isNaN(value), 'Failed to parse parameter value: ' + text);
|
||||
pixels = value * unitToPixels[unit as keyof typeof unitToPixels];
|
||||
} else {
|
||||
throw new Error(
|
||||
'page.pdf() Cannot handle parameter type: ' + typeof parameter
|
||||
);
|
||||
}
|
||||
return pixels / unitToPixels[lengthUnit];
|
||||
}
|
||||
|
||||
/** @see https://w3c.github.io/webdriver-bidi/#normalize-rect */
|
||||
function normalizeRectangle<BoundingBoxType extends BoundingBox>(
|
||||
clip: Readonly<BoundingBoxType>
|
||||
|
@ -48,6 +48,7 @@ import {
|
||||
debugError,
|
||||
evaluationString,
|
||||
NETWORK_IDLE_TIME,
|
||||
parsePDFOptions,
|
||||
timeout,
|
||||
validateDialogType,
|
||||
waitForHTTP,
|
||||
@ -586,7 +587,8 @@ export class BidiPage extends Page {
|
||||
}
|
||||
|
||||
override async pdf(options: PDFOptions = {}): Promise<Buffer> {
|
||||
const {path = undefined} = options;
|
||||
const {timeout: ms = this._timeoutSettings.timeout(), path = undefined} =
|
||||
options;
|
||||
const {
|
||||
printBackground: background,
|
||||
margin,
|
||||
@ -596,8 +598,7 @@ export class BidiPage extends Page {
|
||||
pageRanges: ranges,
|
||||
scale,
|
||||
preferCSSPageSize,
|
||||
timeout: ms,
|
||||
} = this._getPDFOptions(options, 'cm');
|
||||
} = parsePDFOptions(options, 'cm');
|
||||
const pageRanges = ranges ? ranges.split(', ') : [];
|
||||
const {result} = await firstValueFrom(
|
||||
from(
|
||||
|
@ -45,6 +45,7 @@ import {
|
||||
getReadableFromProtocolStream,
|
||||
NETWORK_IDLE_TIME,
|
||||
pageBindingInitString,
|
||||
parsePDFOptions,
|
||||
timeout,
|
||||
validateDialogType,
|
||||
valueFromRemoteObject,
|
||||
@ -1134,6 +1135,7 @@ export class CdpPage extends Page {
|
||||
}
|
||||
|
||||
override async createPDFStream(options: PDFOptions = {}): Promise<Readable> {
|
||||
const {timeout: ms = this._timeoutSettings.timeout()} = options;
|
||||
const {
|
||||
landscape,
|
||||
displayHeaderFooter,
|
||||
@ -1147,9 +1149,8 @@ export class CdpPage extends Page {
|
||||
pageRanges,
|
||||
preferCSSPageSize,
|
||||
omitBackground,
|
||||
timeout: ms,
|
||||
tagged: generateTaggedPDF,
|
||||
} = this._getPDFOptions(options);
|
||||
} = parsePDFOptions(options);
|
||||
|
||||
if (omitBackground) {
|
||||
await this.#emulationManager.setTransparentBackgroundColor();
|
||||
|
@ -195,7 +195,7 @@ export interface ParsedPDFOptionsInterface {
|
||||
* @internal
|
||||
*/
|
||||
export type ParsedPDFOptions = Required<
|
||||
Omit<PDFOptions, 'path' | 'format'> & ParsedPDFOptionsInterface
|
||||
Omit<PDFOptions, 'path' | 'format' | 'timeout'> & ParsedPDFOptionsInterface
|
||||
>;
|
||||
|
||||
/**
|
||||
|
@ -9,11 +9,11 @@ import type {Readable} from 'stream';
|
||||
|
||||
import type {Protocol} from 'devtools-protocol';
|
||||
|
||||
import type {Observable} from '../../third_party/rxjs/rxjs.js';
|
||||
import {
|
||||
map,
|
||||
NEVER,
|
||||
timer,
|
||||
type Observable,
|
||||
firstValueFrom,
|
||||
fromEvent,
|
||||
filterAsync,
|
||||
@ -30,6 +30,12 @@ import {debug} from './Debug.js';
|
||||
import {TimeoutError} from './Errors.js';
|
||||
import type {EventEmitter, EventType} from './EventEmitter.js';
|
||||
import type {NetworkManagerEvents} from './NetworkManagerEvents.js';
|
||||
import type {
|
||||
LowerCasePaperFormat,
|
||||
ParsedPDFOptions,
|
||||
PDFOptions,
|
||||
} from './PDFOptions.js';
|
||||
import {paperFormats} from './PDFOptions.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -609,3 +615,99 @@ export async function waitForHTTP<T extends {url(): string}>(
|
||||
* @internal
|
||||
*/
|
||||
export const NETWORK_IDLE_TIME = 500;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function parsePDFOptions(
|
||||
options: PDFOptions = {},
|
||||
lengthUnit: 'in' | 'cm' = 'in'
|
||||
): ParsedPDFOptions {
|
||||
const defaults: Omit<ParsedPDFOptions, 'width' | 'height' | 'margin'> = {
|
||||
scale: 1,
|
||||
displayHeaderFooter: false,
|
||||
headerTemplate: '',
|
||||
footerTemplate: '',
|
||||
printBackground: false,
|
||||
landscape: false,
|
||||
pageRanges: '',
|
||||
preferCSSPageSize: false,
|
||||
omitBackground: false,
|
||||
tagged: false,
|
||||
};
|
||||
|
||||
let width = 8.5;
|
||||
let height = 11;
|
||||
if (options.format) {
|
||||
const format =
|
||||
paperFormats[options.format.toLowerCase() as LowerCasePaperFormat];
|
||||
assert(format, 'Unknown paper format: ' + options.format);
|
||||
width = format.width;
|
||||
height = format.height;
|
||||
} else {
|
||||
width = convertPrintParameterToInches(options.width, lengthUnit) ?? width;
|
||||
height =
|
||||
convertPrintParameterToInches(options.height, lengthUnit) ?? height;
|
||||
}
|
||||
|
||||
const margin = {
|
||||
top: convertPrintParameterToInches(options.margin?.top, lengthUnit) || 0,
|
||||
left: convertPrintParameterToInches(options.margin?.left, lengthUnit) || 0,
|
||||
bottom:
|
||||
convertPrintParameterToInches(options.margin?.bottom, lengthUnit) || 0,
|
||||
right:
|
||||
convertPrintParameterToInches(options.margin?.right, lengthUnit) || 0,
|
||||
};
|
||||
|
||||
return {
|
||||
...defaults,
|
||||
...options,
|
||||
width,
|
||||
height,
|
||||
margin,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const unitToPixels = {
|
||||
px: 1,
|
||||
in: 96,
|
||||
cm: 37.8,
|
||||
mm: 3.78,
|
||||
};
|
||||
|
||||
function convertPrintParameterToInches(
|
||||
parameter?: string | number,
|
||||
lengthUnit: 'in' | 'cm' = 'in'
|
||||
): number | undefined {
|
||||
if (typeof parameter === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
let pixels;
|
||||
if (isNumber(parameter)) {
|
||||
// Treat numbers as pixel values to be aligned with phantom's paperSize.
|
||||
pixels = parameter;
|
||||
} else if (isString(parameter)) {
|
||||
const text = parameter;
|
||||
let unit = text.substring(text.length - 2).toLowerCase();
|
||||
let valueText = '';
|
||||
if (unit in unitToPixels) {
|
||||
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;
|
||||
}
|
||||
const value = Number(valueText);
|
||||
assert(!isNaN(value), 'Failed to parse parameter value: ' + text);
|
||||
pixels = value * unitToPixels[unit as keyof typeof unitToPixels];
|
||||
} else {
|
||||
throw new Error(
|
||||
'page.pdf() Cannot handle parameter type: ' + typeof parameter
|
||||
);
|
||||
}
|
||||
return pixels / unitToPixels[lengthUnit];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user