Skip to content

Commit

Permalink
Custom headers and footers (#129)
Browse files Browse the repository at this point in the history
* Add new header/footer template options.

* Add basic custom header/footer test.

* Add custom header & footer docs.

* Update version to 0.5.0.
  • Loading branch information
westy92 authored Mar 7, 2018
1 parent 421610e commit 6e8cc99
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 2 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,43 @@ const html = template(templateData);
const pdf = await htmlPdf.create(html, options);
```

### Custom Headers and Footers

_Note: Requires Chrome 65 or later._

You can optionally provide an HTML template for a custom header and/or footer.

A few classes can be used to inject printing values:

* `date` - formatted print date
* `title` - document title
* `url` - document location
* `pageNumber` - current page number
* `totalPages` - total pages in the document

You can tweak the margins with the `printOptions` of `marginTop`, `marginBottom`, `marginLeft`, and `marginRight`.

At this time, you must inline any images using [base64 encoding](http://www.bigfastblog.com/embed-base64-encoded-images-inline-in-html).

You can view how Chrome lays out the templates [here](https://cs.chromium.org/chromium/src/components/printing/resources/print_preview_page.html).

#### Example

```js
const pdf = await htmlPdf.create(html, {
port,
printOptions: {
displayHeaderFooter: true,
headerTemplate: `
<div class="text center">
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>
`,
footerTemplate: '<div class="text center">Custom footer!</div>',
},
});
```

### Trigger Render Completion

There are a few `CompletionTrigger` types that wait for something to occur before triggering PDF printing.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "html-pdf-chrome",
"version": "0.4.3",
"version": "0.5.0",
"description": "HTML to PDF converter via Chrome/Chromium",
"main": "lib/src/index.js",
"scripts": {
Expand Down
34 changes: 33 additions & 1 deletion src/typings/chrome/Page/PrintToPDFOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

/**
* Chrome Page.printToPDF options.
* Note: these require Chrome >= 60.
*
* @export
* @interface PrintToPDFOptions
Expand Down Expand Up @@ -105,4 +104,37 @@ export default interface PrintToPDFOptions {
* @memberof PrintToPDFOptions
*/
ignoreInvalidPageRanges?: boolean;

/**
* HTML template for the print header.
* Should be valid HTML markup with following classes used to inject printing values into them:
* - `date` formatted print date
* - `title` document title
* - `url` document location
* - `pageNumber` current page number
* - `totalPages` total pages in the document
*
* For example, `<span class="title"></span>` would generate a span containing the title.
*
* @type {string}
* @memberof PrintToPDFOptions
*/
headerTemplate?: string;

/**
* HTML template for the print footer. Should use the same format as the `headerTemplate`.
*
* @type {string}
* @memberof PrintToPDFOptions
*/
footerTemplate?: string;

/**
* Whether or not to prefer page size as defined by css.
* Defaults to false, in which case the content will be scaled to fit the paper size.
*
* @type {boolean}
* @memberof PrintToPDFOptions
*/
preferCSSPageSize?: boolean;
}
37 changes: 37 additions & 0 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ describe('HtmlPdf', () => {
'--disable-gpu',
'--headless',
],
// uncomment if using Chrome Beta
// chromePath: '/usr/bin/google-chrome-beta',
connectionPollInterval: 250,
logLevel: 'error',
maxConnectionRetries: 50,
Expand Down Expand Up @@ -245,6 +247,41 @@ describe('HtmlPdf', () => {
expect(pdf.getRawTextContent()).to.contain('Page (0) Break').and.to.contain('Page (1) Break');
});

it('should generate a PDF with custom headers and footers', async () => {
const html = `
<html>
<head>
<title>TITLE</title>
</head>
<body>
<div style="page-break-after:always">P1</div>
<div>P2</div>
</body>
</html>
`;
const result = await HtmlPdf.create(html, {
port,
printOptions: {
displayHeaderFooter: true,
headerTemplate: `
<div class="text center" style="color:red;">
Custom <b>header</b>!
Page <span class="pageNumber"></span> of <span class="totalPages"></span>.
Title: <span class="title"></span>.
</div>
`,
footerTemplate: '<div class="text center" style="color:green">Custom <i>footer</i>!</div>',
},
});
expect(result).to.be.an.instanceOf(HtmlPdf.CreateResult);
const pdf = await getParsedPdf(result.toBuffer());
const pdfText = pdf.getRawTextContent();
expect(pdfText).to.contain('Custom header!').and.to.contain('Custom footer!');
expect(pdfText).to.contain('Page 1 of 2.').and.to.contain('Page 2 of 2.');
expect(pdfText).to.contain('P1').and.to.contain('P2');
expect(pdfText).to.contain('Title: TITLE.');
});

it('should generate a PDF from a local file', async () => {
const filePath = path.join('file://', __dirname, '../../test/test.html');
const result = await HtmlPdf.create(filePath, {port});
Expand Down

0 comments on commit 6e8cc99

Please sign in to comment.