Skip to content

Commit

Permalink
Add hyperlink support
Browse files Browse the repository at this point in the history
  • Loading branch information
eKoopmans committed Mar 31, 2017
1 parent 81ab9d2 commit a6cb4ef
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 15 deletions.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ html2pdf converts any webpage or element into a printable PDF entirely client-si
<script src="html2pdf.js"></script>
```

**Note:** For best results, use the custom build of `html2canvas` found in the `vendor` folder or at [this repo](https://github.com/eKoopmans/html2canvas/tree/develop).
**Note:** For best results, use the custom builds of `html2canvas` and `jsPDF` found in the `vendor` folder, which contain added features and hotfixes.

## Usage

Expand Down Expand Up @@ -42,19 +42,20 @@ html2pdf(element, {

The `opt` parameter has the following optional fields:

|Field |Value(s) |Description |
|------------|----------------|---------------------------------------------------------------------------------------------|
|margin |number or array |PDF margin (default=1). Array can be either [vMargin, hMargin] or [top, left, bottom, right].|
|filename |string |The default filename of the exported PDF (default='file.pdf'). |
|image |object |The image type used to generate the PDF. It must have two fields: 'type', the image type ('jpeg'/'png'); and 'quality', the image quality (0-1). See [here](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL) for more info (do not include 'image/' in the 'type' field).|
|html2canvas |object |Configuration options sent directly to `html2canvas` ([see here](https://github.com/niklasvh/html2canvas) for usage).|
|jsPDF |object |Configuration options sent directly to `jsPDF` ([see here](https://github.com/MrRio/jsPDF) for usage. |
|Name |Type |Default |Description |
|------------|----------------|------------------------------|---------------------------------------------------------------------------------------------|
|margin |number or array |1 |PDF margin. Array can be either [vMargin, hMargin] or [top, left, bottom, right]. |
|filename |string |'file.pdf' |The default filename of the exported PDF. |
|image |object |{type: 'jpeg', quality: 0.95} |The image type used to generate the PDF. It must have two fields: 'type', the image type ('jpeg'/'png'); and 'quality', the image quality (0-1). See [here](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL) for more info (do not include 'image/' in the 'type' field).|
|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](https://github.com/niklasvh/html2canvas) for usage).|
|jsPDF |object |{ } |Configuration options sent directly to `jsPDF` ([see here](https://github.com/MrRio/jsPDF) for usage. |

## Dependencies

html2pdf depends on the external packages [`html2canvas`](https://github.com/niklasvh/html2canvas) and [`jsPDF`](https://github.com/MrRio/jsPDF).

For best results, use [this custom build](https://github.com/eKoopmans/html2canvas/tree/develop) of `html2canvas`, which adds support for box-shadows and custom resolutions (via the `dpi`/`scale` options).
For best results, use [this custom build](https://github.com/eKoopmans/html2canvas/tree/develop) of `html2canvas`, which adds support for box-shadows and custom resolutions (via the `dpi`/`scale` options), and [this build](https://github.com/eKoopmans/html2pdf/blob/master/vendor/jspdf.min.js) of jsPDF, which contains a hotfix for hyperlinks.

## Credits

Expand Down
44 changes: 39 additions & 5 deletions src/html2pdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ var html2pdf = (function(html2canvas, jsPDF) {
var container = html2pdf.makeContainer(source, pageSize);
var overlay = container.parentElement;

// Get the locations of all hyperlinks.
if (opt.enableLinks) {
var links = container.querySelectorAll('a');
var containerRect = unitConvert(container.getBoundingClientRect(), pageSize.k);
opt.links = Array.prototype.map.call(links, function(link) {
var clientRect = unitConvert(link.getBoundingClientRect(), pageSize.k);
clientRect.left -= containerRect.left;
clientRect.top -= containerRect.top;
return { el: link, clientRect: clientRect };
});
}

// Render the canvas and pass the result to makePDF.
var onRendered = opt.html2canvas.onrendered || function() {};
opt.html2canvas.onrendered = function(canvas) {
Expand Down Expand Up @@ -81,6 +93,7 @@ var html2pdf = (function(html2canvas, jsPDF) {
opt.jsPDF = opt.jsPDF || {};
opt.html2canvas = opt.html2canvas || {};
opt.filename = opt.filename && objType(opt.filename) === 'string' ? opt.filename : 'file.pdf';
opt.enableLinks = opt.hasOwnProperty('enableLinks') ? opt.enableLinks : true;
opt.image = opt.image || {};
opt.image.type = opt.image.type || 'jpeg';
opt.image.quality = opt.image.quality || 0.95;
Expand Down Expand Up @@ -148,11 +161,11 @@ var html2pdf = (function(html2canvas, jsPDF) {

// Break the full canvas into pages, then reduce it to one page.
var ctx = canvas.getContext('2d');
var fullHeight = canvas.height;
var pageHeight = Math.floor(canvas.width * pageSize.inner.ratio);
var nPages = Math.ceil(fullHeight / pageHeight);
var pxFullHeight = canvas.height;
var pxPageHeight = Math.floor(canvas.width * pageSize.inner.ratio);
var nPages = Math.ceil(pxFullHeight / pxPageHeight);
var imgFull = ctx.getImageData(0, 0, canvas.width, canvas.height);
canvas.height = pageHeight;
canvas.height = pxPageHeight;

// Initialize the PDF.
var pdf = new jsPDF(opt.jsPDF);
Expand All @@ -161,13 +174,25 @@ var html2pdf = (function(html2canvas, jsPDF) {
// Display the page (fill with white a bit past the render edge just in case).
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(-10, -10, canvas.width+20, canvas.height+20);
ctx.putImageData(imgFull, 0, -page*pageHeight);
ctx.putImageData(imgFull, 0, -page*pxPageHeight);

// Add the page to the PDF.
if (page) pdf.addPage();
var imgData = canvas.toDataURL('image/' + opt.image.type, opt.image.quality);
pdf.addImage(imgData, opt.image.type, opt.margin[1], opt.margin[0],
pageSize.inner.width, pageSize.inner.height);

// Add hyperlinks.
if (opt.enableLinks) {
var pageTop = page * pageSize.inner.height;
opt.links.forEach(function(link) {
if (link.clientRect.top > pageTop && link.clientRect.top < pageTop + pageSize.inner.height) {
var left = opt.margin[1] + link.clientRect.left;
var top = opt.margin[0] + link.clientRect.top - pageTop;
pdf.link(left, top, link.clientRect.width, link.clientRect.height, { url: link.el.href });
}
});
}
}

// Finish the PDF.
Expand Down Expand Up @@ -199,6 +224,15 @@ var html2pdf = (function(html2canvas, jsPDF) {
return el;
};

// Convert units using the conversion value 'k' from jsPDF.
var unitConvert = function(obj, k) {
var newObj = {};
for (var key in obj) {
newObj[key] = obj[key] * 72 / 96 / k;
}
return newObj;
};

// Get dimensions of a PDF page, as determined by jsPDF.
jsPDF.getPageSize = function(orientation, unit, format) {
// Decode options object
Expand Down
2 changes: 1 addition & 1 deletion vendor/jspdf.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a6cb4ef

Please sign in to comment.