mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat: add outline to PDF generation (#11779)
This commit is contained in:
parent
2c3711e885
commit
b99d478cd4
@ -24,6 +24,7 @@ export interface PDFOptions
|
|||||||
| landscape | <code>optional</code> | boolean | Whether to print in landscape orientation. | <code>false</code> |
|
| landscape | <code>optional</code> | boolean | Whether to print in landscape orientation. | <code>false</code> |
|
||||||
| margin | <code>optional</code> | [PDFMargin](./puppeteer.pdfmargin.md) | Set the PDF margins. | <code>undefined</code> no margins are set. |
|
| margin | <code>optional</code> | [PDFMargin](./puppeteer.pdfmargin.md) | Set the PDF margins. | <code>undefined</code> no margins are set. |
|
||||||
| omitBackground | <code>optional</code> | boolean | Hides default white background and allows generating pdfs with transparency. | <code>false</code> |
|
| omitBackground | <code>optional</code> | boolean | Hides default white background and allows generating pdfs with transparency. | <code>false</code> |
|
||||||
|
| outline | <code>optional</code> | boolean | Generate document outline. | <code>false</code> |
|
||||||
| pageRanges | <code>optional</code> | string | Paper ranges to print, e.g. <code>1-5, 8, 11-13</code>. | The empty string, which means all pages are printed. |
|
| pageRanges | <code>optional</code> | string | Paper ranges to print, e.g. <code>1-5, 8, 11-13</code>. | The empty string, which means all pages are printed. |
|
||||||
| path | <code>optional</code> | string | The path to save the file to. | <code>undefined</code>, which means the PDF will not be written to disk. |
|
| path | <code>optional</code> | string | The path to save the file to. | <code>undefined</code>, which means the PDF will not be written to disk. |
|
||||||
| preferCSSPageSize | <code>optional</code> | boolean | Give any CSS <code>@page</code> size declared in the page priority over what is declared in the <code>width</code> or <code>height</code> or <code>format</code> option. | <code>false</code>, which will scale the content to fit the paper size. |
|
| preferCSSPageSize | <code>optional</code> | boolean | Give any CSS <code>@page</code> size declared in the page priority over what is declared in the <code>width</code> or <code>height</code> or <code>format</code> option. | <code>false</code>, which will scale the content to fit the paper size. |
|
||||||
|
@ -1102,6 +1102,7 @@ export class CdpPage extends Page {
|
|||||||
preferCSSPageSize,
|
preferCSSPageSize,
|
||||||
omitBackground,
|
omitBackground,
|
||||||
tagged: generateTaggedPDF,
|
tagged: generateTaggedPDF,
|
||||||
|
outline: generateDocumentOutline,
|
||||||
} = parsePDFOptions(options);
|
} = parsePDFOptions(options);
|
||||||
|
|
||||||
if (omitBackground) {
|
if (omitBackground) {
|
||||||
@ -1127,6 +1128,7 @@ export class CdpPage extends Page {
|
|||||||
pageRanges,
|
pageRanges,
|
||||||
preferCSSPageSize,
|
preferCSSPageSize,
|
||||||
generateTaggedPDF,
|
generateTaggedPDF,
|
||||||
|
generateDocumentOutline,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -162,6 +162,18 @@ export interface PDFOptions {
|
|||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
tagged?: boolean;
|
tagged?: boolean;
|
||||||
|
/**
|
||||||
|
* Generate document outline.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* If this is enabled the PDF will also be tagged (accessible)
|
||||||
|
* Currently only works in old Headless (headless = true)
|
||||||
|
* crbug/840455#c47
|
||||||
|
*
|
||||||
|
* @defaultValue `false`
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
outline?: boolean;
|
||||||
/**
|
/**
|
||||||
* Timeout in milliseconds. Pass `0` to disable timeout.
|
* Timeout in milliseconds. Pass `0` to disable timeout.
|
||||||
* @defaultValue `30_000`
|
* @defaultValue `30_000`
|
||||||
|
@ -350,6 +350,7 @@ export function parsePDFOptions(
|
|||||||
preferCSSPageSize: false,
|
preferCSSPageSize: false,
|
||||||
omitBackground: false,
|
omitBackground: false,
|
||||||
tagged: false,
|
tagged: false,
|
||||||
|
outline: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let width = 8.5;
|
let width = 8.5;
|
||||||
@ -375,6 +376,11 @@ export function parsePDFOptions(
|
|||||||
convertPrintParameterToInches(options.margin?.right, lengthUnit) || 0,
|
convertPrintParameterToInches(options.margin?.right, lengthUnit) || 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Quirk https://bugs.chromium.org/p/chromium/issues/detail?id=840455#c44
|
||||||
|
if (options.outline) {
|
||||||
|
options.tagged = true;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...defaults,
|
...defaults,
|
||||||
...options,
|
...options,
|
||||||
|
@ -231,6 +231,7 @@ export class ChromeLauncher extends ProductLauncher {
|
|||||||
'--disable-sync',
|
'--disable-sync',
|
||||||
'--enable-automation',
|
'--enable-automation',
|
||||||
'--export-tagged-pdf',
|
'--export-tagged-pdf',
|
||||||
|
'--generate-pdf-document-outline',
|
||||||
'--force-color-profile=srgb',
|
'--force-color-profile=srgb',
|
||||||
'--metrics-recording-only',
|
'--metrics-recording-only',
|
||||||
'--no-first-run',
|
'--no-first-run',
|
||||||
|
@ -233,6 +233,12 @@
|
|||||||
"parameters": ["webDriverBiDi"],
|
"parameters": ["webDriverBiDi"],
|
||||||
"expectations": ["FAIL"]
|
"expectations": ["FAIL"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[pdf.spec] Page.pdf *",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["webDriverBiDi"],
|
||||||
|
"expectations": ["SKIP"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[prerender.spec] *",
|
"testIdPattern": "[prerender.spec] *",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -943,12 +949,6 @@
|
|||||||
"parameters": ["webDriverBiDi"],
|
"parameters": ["webDriverBiDi"],
|
||||||
"expectations": ["FAIL"]
|
"expectations": ["FAIL"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"testIdPattern": "[page.spec] Page Page.pdf can print to PDF with accessible",
|
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
|
||||||
"parameters": ["webDriverBiDi"],
|
|
||||||
"expectations": ["SKIP"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"testIdPattern": "[page.spec] Page Page.pdf should respect timeout",
|
"testIdPattern": "[page.spec] Page Page.pdf should respect timeout",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -1003,6 +1003,12 @@
|
|||||||
"parameters": ["webDriverBiDi"],
|
"parameters": ["webDriverBiDi"],
|
||||||
"expectations": ["FAIL", "PASS", "TIMEOUT"]
|
"expectations": ["FAIL", "PASS", "TIMEOUT"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[pdf.spec] Page.pdf *",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["cdp", "firefox"],
|
||||||
|
"expectations": ["SKIP"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[prerender.spec] Prerender can screencast",
|
"testIdPattern": "[prerender.spec] Prerender can screencast",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -3002,12 +3008,6 @@
|
|||||||
"parameters": ["cdp", "firefox"],
|
"parameters": ["cdp", "firefox"],
|
||||||
"expectations": ["FAIL"]
|
"expectations": ["FAIL"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"testIdPattern": "[page.spec] Page Page.pdf can print to PDF with accessible",
|
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
|
||||||
"parameters": ["cdp", "firefox"],
|
|
||||||
"expectations": ["SKIP"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"testIdPattern": "[page.spec] Page Page.removeExposedFunction should work",
|
"testIdPattern": "[page.spec] Page Page.removeExposedFunction should work",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -3128,6 +3128,18 @@
|
|||||||
"parameters": ["cdp", "firefox"],
|
"parameters": ["cdp", "firefox"],
|
||||||
"expectations": ["FAIL"]
|
"expectations": ["FAIL"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[pdf.spec] Page.pdf can print to PDF with outline",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headful"],
|
||||||
|
"expectations": ["FAIL"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[pdf.spec] Page.pdf can print to PDF with outline",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "new-headless"],
|
||||||
|
"expectations": ["FAIL"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[prerender.spec] Prerender can navigate to a prerendered page via Puppeteer",
|
"testIdPattern": "[prerender.spec] Prerender can navigate to a prerendered page via Puppeteer",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
@ -6,6 +6,12 @@
|
|||||||
<title>PDF</title>
|
<title>PDF</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div>PDF Content</div>
|
<h1>PDF Content</h1>
|
||||||
|
<section>
|
||||||
|
<h1>PDF Subcontent 1</h1>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h1>PDF Subcontent 2</h1>
|
||||||
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
55
test/src/cdp/pdf.spec.ts
Normal file
55
test/src/cdp/pdf.spec.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2017 Google Inc.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {readFile, unlink} from 'fs/promises';
|
||||||
|
|
||||||
|
import expect from 'expect';
|
||||||
|
|
||||||
|
import {getTestState, setupTestBrowserHooks} from '../mocha-utils.js';
|
||||||
|
|
||||||
|
describe('Page.pdf', () => {
|
||||||
|
setupTestBrowserHooks();
|
||||||
|
|
||||||
|
it('can print to PDF with accessible', async () => {
|
||||||
|
const {page, server} = await getTestState();
|
||||||
|
|
||||||
|
const outputFile = __dirname + '/../../assets/output.pdf';
|
||||||
|
const outputFileAccessible =
|
||||||
|
__dirname + '/../../assets/output-accessible.pdf';
|
||||||
|
await page.goto(server.PREFIX + '/pdf.html');
|
||||||
|
await page.pdf({path: outputFile});
|
||||||
|
await page.pdf({path: outputFileAccessible, tagged: true});
|
||||||
|
try {
|
||||||
|
const [base, tagged] = await Promise.all([
|
||||||
|
readFile(outputFile),
|
||||||
|
readFile(outputFileAccessible),
|
||||||
|
]);
|
||||||
|
expect(tagged.byteLength).toBeGreaterThan(base.byteLength);
|
||||||
|
} finally {
|
||||||
|
await Promise.all([unlink(outputFile), unlink(outputFileAccessible)]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can print to PDF with outline', async () => {
|
||||||
|
const {page, server} = await getTestState();
|
||||||
|
|
||||||
|
const outputFile = __dirname + '/../../assets/output.pdf';
|
||||||
|
const outputFileOutlined = __dirname + '/../../assets/output-outlined.pdf';
|
||||||
|
await page.goto(server.PREFIX + '/pdf.html');
|
||||||
|
await page.pdf({path: outputFile, tagged: true});
|
||||||
|
await page.pdf({path: outputFileOutlined, tagged: true, outline: true});
|
||||||
|
try {
|
||||||
|
const [base, outlined] = await Promise.all([
|
||||||
|
readFile(outputFile),
|
||||||
|
readFile(outputFileOutlined),
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(outlined.byteLength).toBeGreaterThan(base.byteLength);
|
||||||
|
} finally {
|
||||||
|
await Promise.all([unlink(outputFile), unlink(outputFileOutlined)]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -1940,25 +1940,6 @@ describe('Page', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can print to PDF with accessible', async () => {
|
|
||||||
const {page, server} = await getTestState();
|
|
||||||
|
|
||||||
const outputFile = __dirname + '/../assets/output.pdf';
|
|
||||||
const outputFileAccessible =
|
|
||||||
__dirname + '/../assets/output-accessible.pdf';
|
|
||||||
await page.goto(server.PREFIX + '/pdf.html');
|
|
||||||
await page.pdf({path: outputFile});
|
|
||||||
await page.pdf({path: outputFileAccessible, tagged: true});
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
fs.readFileSync(outputFileAccessible).byteLength
|
|
||||||
).toBeGreaterThan(fs.readFileSync(outputFile).byteLength);
|
|
||||||
} finally {
|
|
||||||
fs.unlinkSync(outputFileAccessible);
|
|
||||||
fs.unlinkSync(outputFile);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can print to PDF and stream the result', async () => {
|
it('can print to PDF and stream the result', async () => {
|
||||||
const {page} = await getTestState();
|
const {page} = await getTestState();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user