@davidnbooth/html2pdf
v0.11.1
Published
Fork of html2pdf.js by eKoopmans
Downloads
2
Maintainers
Readme
FORK NOTES:
THIS IS JUST A FORK OF html2pdf.js, it is not an original work. I needed some changes for my own project, so I am working on it here.
My changes so far:
- Fully updated all the dependencies. All npm scripts run (tested all except publish/release, with npm v9 and node v18).
- Pulled .convert() out of the Worker object, I don't think it needs to be part of it and this simplifies the Worker.
- jsdoc comments for all Worker methods and properties, and the functions in utils.js. Installed jsdoc as devDependency and created docs.
- Dropped support for environments that don't have native Promises. This proved to be a significant bug fix for my use case.
- Removed
setProgress
function in favour of just usingupdateProgress
and manually setting the initial properties - helps the type checker & reduces # of methods. - Initial implementation of the progress-tracking feature. I don't think it's quite right, but the basics are there.
Notes on current PRs:
- All the dependabot ones should be resolved by my changes here.
- #569 looks good, combine with #340 and document why the calculation is done that way
- I think #531 looks good, need to jsdoc the new function
- #516 is interesting - one canvas per page. This is a resolution for issue #5 listed at the bottom of this document. #300 also discusses this issue. Also seems related to #314. All that said, maybe the real solution is to do what's discussed in issue #4 at the bottom of this document, and use new jsPDF features instead of using html2canvas at all.
- #503 is super trivial but good
- #354 is no longer relevant
- #170 looks good, probably need to document the option?
- #447 is probably good
- #260/#261 seem reasonable
- #235, meh, as eKoopmans said, changing the renderer is a bigger project
- #228, meh, sounds like its a problem with how the other library exposes the html2pdf object?
- #179, meh, see existing response.
- #41, idk, it might be too old to be still relevant?
To do:
- Finish the progress api
html2pdf.js
html2pdf.js converts any webpage or element into a printable PDF entirely client-side using html2canvas and jsPDF.
:warning: There have been several issues reported in v0.10. They are being investigated but in the meantime you may wish to remain on v0.9.3 ("^0.9.3" in npm, or use cdnjs for HTML script tags).
Table of contents
Getting started
CDN
The simplest way to use html2pdf.js is to include it as a script in your HTML by using cdnjs:
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js" integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Using a CDN URL will lock you to a specific version, which should ensure stability and give you control over when to change versions. cdnjs gives you access to all past versions of html2pdf.js.
Note: Read about dependences for more information about using the unbundled version dist/html2canvas.min.js
.
Raw JS
You may also download dist/html2pdf.bundle.min.js
directly to your project folder and include it in your HTML with:
<script src="html2pdf.bundle.min.js"></script>
NPM
Install html2pdf.js and its dependencies using NPM with npm install --save html2pdf.js
(make sure to include .js
in the package name).
Note: You can use NPM to create your project, but html2pdf.js will not run in Node.js, it must be run in a browser.
Bower
Install html2pdf.js and its dependencies using Bower with bower install --save html2pdf.js
(make sure to include .js
in the package name).
Console
If you're on a webpage that you can't modify directly and wish to use html2pdf.js to capture a screenshot, you can follow these steps:
- Open your browser's console (instructions for different browsers here).
- Paste in this code:
function addScript(url) { var script = document.createElement('script'); script.type = 'application/javascript'; script.src = url; document.head.appendChild(script); } addScript('https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js');
- You may now execute html2pdf.js commands directly from the console. To capture a default PDF of the entire page, use
html2pdf(document.body)
.
Usage
Once installed, html2pdf.js is ready to use. The following command will generate a PDF of #element-to-print
and prompt the user to save the result:
var element = document.getElementById('element-to-print');
html2pdf(element);
Advanced usage
Every step of html2pdf.js is configurable, using its new Promise-based API. If html2pdf.js is called without arguments, it will return a Worker
object:
var worker = html2pdf(); // Or: var worker = new html2pdf.Worker;
This worker has methods that can be chained sequentially, as each Promise resolves, and allows insertion of your own intermediate functions between steps. A prerequisite system allows you to skip over mandatory steps (like canvas creation) without any trouble:
// This will implicitly create the canvas and PDF objects before saving.
var worker = html2pdf().from(element).save();
Workflow
The basic workflow of html2pdf.js tasks (enforced by the prereq system) is:
.from() -> .toContainer() -> .toCanvas() -> .toImg() -> .toPdf() -> .save()
Worker API
| Method | Arguments | Description |
|--------------|--------------------|-------------|
| from | src, type | Sets the source (HTML string or element) for the PDF. Optional type
specifies other sources: 'string'
, 'element'
, 'canvas'
, or 'img'
. |
| to | target | Converts the source to the specified target ('container'
, 'canvas'
, 'img'
, or 'pdf'
). Each target also has its own toX
method that can be called directly: toContainer()
, toCanvas()
, toImg()
, and toPdf()
. |
| output | type, options, src | Routes to the appropriate outputPdf
or outputImg
method based on specified src
('pdf'
(default) or 'img'
). |
| outputPdf | type, options | Sends type
and options
to the jsPDF object's output
method, and returns the result as a Promise (use .then
to access). See the jsPDF source code for more info. |
| outputImg | type, options | Returns the specified data type for the image as a Promise (use .then
to access). Supported types: 'img'
, 'datauristring'
/'dataurlstring'
, and 'datauri'
/'dataurl'
. |
| save | filename | Saves the PDF object with the optional filename (creates user download prompt). |
| set | opt | Sets the specified properties. See Options below for more details. |
| get | key, cbk | Returns the property specified in key
, either as a Promise (use .then
to access), or by calling cbk
if provided. |
| then | onFulfilled, onRejected | Standard Promise method, with this
re-bound to the Worker, and with added progress-tracking (see Progress below). Note that .then
returns a Worker
, which is a subclass of Promise. |
| thenCore | onFulFilled, onRejected | Standard Promise method, with this
re-bound to the Worker (no progress-tracking). Note that .thenCore
returns a Worker
, which is a subclass of Promise. |
| thenExternal | onFulfilled, onRejected | True Promise method. Using this 'exits' the Worker chain - you will not be able to continue chaining Worker methods after .thenExternal
. |
| catch, catchExternal | onRejected | Standard Promise method. catchExternal
exits the Worker chain - you will not be able to continue chaining Worker methods after .catchExternal
. |
| error | msg | Throws an error in the Worker's Promise chain. |
| listen | (progress) => void | Lets you pass a callback that will be called after each step of the html2pdf process completes. Useful for making progress bars, etc. |
A few aliases are also provided for convenience:
| Method | Alias | |-----------|-----------| | save | saveAs | | set | using | | output | export | | then | run |
Options
html2pdf.js can be configured using an optional opt
parameter:
var element = document.getElementById('element-to-print');
var opt = {
margin: 1,
filename: 'myfile.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2 },
jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
};
// New Promise-based usage:
html2pdf().set(opt).from(element).save();
// Old monolithic-style usage:
html2pdf(element, opt);
The opt
parameter has the following optional fields:
|Name |Type |Default |Description |
|------------|----------------|--------------------------------|------------------------------------------------------------------------------------------------------------|
|margin |number or array |0
|PDF margin (in jsPDF units). Can be a single number, [vMargin, hMargin]
, or [top, left, bottom, right]
. |
|filename |string |'file.pdf'
|The default filename of the exported PDF. |
|pagebreak |object |{mode: ['css', 'legacy']}
|Controls the pagebreak behaviour on the page. See Page-breaks below. |
|image |object |{type: 'jpeg', quality: 0.95}
|The image type and quality used to generate the PDF. See Image type and quality below.|
|enableLinks |boolean |true
|If enabled, PDF hyperlinks are automatically added ontop of all anchor tags. |
|html2canvas |object |{ }
|Configuration options sent directly to html2canvas
(see here for usage).|
|jsPDF |object |{ }
|Configuration options sent directly to jsPDF
(see here for usage).|
Page-breaks
html2pdf.js has the ability to automatically add page-breaks to clean up your document. Page-breaks can be added by CSS styles, set on individual elements using selectors, or avoided from breaking inside all elements (avoid-all
mode).
By default, html2pdf.js will respect most CSS break-before
, break-after
, and break-inside
rules, and also add page-breaks after any element with class html2pdf__page-break
(for legacy purposes).
Page-break settings
|Setting |Type |Default |Description |
|----------|----------------|--------------------|------------|
|mode |string or array |['css', 'legacy']
|The mode(s) on which to automatically add page-breaks. One or more of 'avoid-all'
, 'css'
, and 'legacy'
. |
|before |string or array |[]
|CSS selectors for which to add page-breaks before each element. Can be a specific element with an ID ('#myID'
), all elements of a type (e.g. 'img'
), all of a class ('.myClass'
), or even '*'
to match every element. |
|after |string or array |[]
|Like 'before', but adds a page-break immediately after the element. |
|avoid |string or array |[]
|Like 'before', but avoids page-breaks on these elements. You can enable this feature on every element using the 'avoid-all' mode. |
Page-break modes
| Mode | Description |
|-----------|-------------|
| avoid-all | Automatically adds page-breaks to avoid splitting any elements across pages. |
| css | Adds page-breaks according to the CSS break-before
, break-after
, and break-inside
properties. Only recognizes always/left/right
for before/after, and avoid
for inside. |
| legacy | Adds page-breaks after elements with class html2pdf__page-break
. This feature may be removed in the future. |
Example usage
// Avoid page-breaks on all elements, and add one before #page2el.
html2pdf().set({
pagebreak: { mode: 'avoid-all', before: '#page2el' }
});
// Enable all 'modes', with no explicit elements.
html2pdf().set({
pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
});
// No modes, only explicit elements.
html2pdf().set({
pagebreak: { before: '.beforeClass', after: ['#after1', '#after2'], avoid: 'img' }
});
Image type and quality
You may customize the image type and quality exported from the canvas by setting the image
option. This must be an object with the following fields:
|Name |Type |Default |Description | |------------|----------------|------------------------------|---------------------------------------------------------------------------------------------| |type |string |'jpeg' |The image type. HTMLCanvasElement only supports 'png', 'jpeg', and 'webp' (on Chrome). | |quality |number |0.95 |The image quality, from 0 to 1. This setting is only used for jpeg/webp (not png). |
These options are limited to the available settings for HTMLCanvasElement.toDataURL(), which ignores quality settings for 'png' images. To enable png image compression, try using the canvas-png-compression shim, which should be an in-place solution to enable png compression via the quality
option.
Progress tracking
The Worker object returned by html2pdf()
has a built-in progress-tracking mechanism. Call the .listen() method at the end of your chain, e.g:
html2pdf().set(opt).from(element).save().listen(progressCallback);
The progressCallback
should be a void function that accepts a single argument, which is this object:
{
val: number - The current progress step.
state: string - A string describing the current step.
n: number - The number of total steps that will be completed.
stack: string[] - The current stack of functions to be executed.
ratio: number - The current progress ratio. (val/n) -> Use this for progress bars!
}
Dependencies
html2pdf.js depends on the external packages html2canvas, and jsPDF). These dependencies are automatically loaded when using NPM or the bundled package.
If using the unbundled dist/html2pdf.min.js
(or its un-minified version), you must also include each dependency. Order is important, otherwise html2canvas will be overridden by jsPDF's own internal implementation:
<script src="jspdf.min.js"></script>
<script src="html2canvas.min.js"></script>
<script src="html2pdf.min.js"></script>
Contributing
Issues
When submitting an issue, please provide reproducible code that highlights the issue, preferably by creating a fork of this template jsFiddle (which has html2pdf.js already loaded). Remember that html2pdf.js uses html2canvas and jsPDF as dependencies, so it's a good idea to check each of those repositories' issue trackers to see if your problem has already been addressed.
Known issues
Rendering: The rendering engine html2canvas isn't perfect (though it's pretty good!). If html2canvas isn't rendering your content correctly, I can't fix it.
- You can test this with something like this fiddle, to see if there's a problem in the canvas creation itself.
Node cloning (CSS etc): The way html2pdf.js clones your content before sending to html2canvas is buggy. A fix is currently being developed - try out:
- direct file: Go to html2pdf.js/bugfix/clone-nodes-BUILD and replace the files in your project with the relevant files (e.g.
dist/html2pdf.bundle.js
) - npm:
npm install eKoopmans/html2pdf.js#bugfix/clone-nodes-BUILD
- Related project: Bugfix: Cloned nodes
- direct file: Go to html2pdf.js/bugfix/clone-nodes-BUILD and replace the files in your project with the relevant files (e.g.
Resizing: Currently, html2pdf.js resizes the root element to fit onto a PDF page (causing internal content to "reflow").
- This is often desired behaviour, but not always.
- There are plans to add alternate behaviour (e.g. "shrink-to-page"), but nothing that's ready to test yet.
- Related project: Feature: Single-page PDFs
Rendered as image: html2pdf.js renders all content into an image, then places that image into a PDF.
- This means text is not selectable or searchable, and causes large file sizes.
- This is currently unavoidable, however recent improvements in jsPDF mean that it may soon be possible to render straight into vector graphics.
- Related project: Feature: New renderer
Maximum size: HTML5 canvases have a maximum height/width. Anything larger will fail to render.
- This is a limitation of HTML5 itself, and results in large PDFs rendering completely blank in html2pdf.js.
- The jsPDF canvas renderer (mentioned in Known Issue #4) may be able to fix this issue!
- Related project: Bugfix: Maximum canvas size
Tests
html2pdf.js is currently sorely lacking in unit tests. Any contributions or suggestions of automated (or manual) tests are welcome. This is high on the to-do list for this project.
Pull requests
If you want to create a new feature or bugfix, please feel free to fork and submit a pull request! Create a fork, branch off of master
, and make changes to the /src/
files (rather than directly to /dist/
). You can test your changes by rebuilding with npm run build
.
Credits
Contributors
Special thanks
- Sauce Labs for unit testing.
License
Copyright (c) 2017-2019 Erik Koopmans <http://www.erik-koopmans.com/>