Skip to content

Commit a6cb4ef

Browse files
committed
Add hyperlink support
1 parent 81ab9d2 commit a6cb4ef

3 files changed

Lines changed: 50 additions & 15 deletions

File tree

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ html2pdf converts any webpage or element into a printable PDF entirely client-si
1414
<script src="html2pdf.js"></script>
1515
```
1616

17-
**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).
17+
**Note:** For best results, use the custom builds of `html2canvas` and `jsPDF` found in the `vendor` folder, which contain added features and hotfixes.
1818

1919
## Usage
2020

@@ -42,19 +42,20 @@ html2pdf(element, {
4242

4343
The `opt` parameter has the following optional fields:
4444

45-
|Field |Value(s) |Description |
46-
|------------|----------------|---------------------------------------------------------------------------------------------|
47-
|margin |number or array |PDF margin (default=1). Array can be either [vMargin, hMargin] or [top, left, bottom, right].|
48-
|filename |string |The default filename of the exported PDF (default='file.pdf'). |
49-
|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).|
50-
|html2canvas |object |Configuration options sent directly to `html2canvas` ([see here](https://github.com/niklasvh/html2canvas) for usage).|
51-
|jsPDF |object |Configuration options sent directly to `jsPDF` ([see here](https://github.com/MrRio/jsPDF) for usage. |
45+
|Name |Type |Default |Description |
46+
|------------|----------------|------------------------------|---------------------------------------------------------------------------------------------|
47+
|margin |number or array |1 |PDF margin. Array can be either [vMargin, hMargin] or [top, left, bottom, right]. |
48+
|filename |string |'file.pdf' |The default filename of the exported PDF. |
49+
|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).|
50+
|enableLinks |boolean |true |If enabled, PDF hyperlinks are automatically added ontop of all anchor tags. |
51+
|html2canvas |object |{ } |Configuration options sent directly to `html2canvas` ([see here](https://github.com/niklasvh/html2canvas) for usage).|
52+
|jsPDF |object |{ } |Configuration options sent directly to `jsPDF` ([see here](https://github.com/MrRio/jsPDF) for usage. |
5253

5354
## Dependencies
5455

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

57-
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).
58+
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.
5859

5960
## Credits
6061

src/html2pdf.js

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ var html2pdf = (function(html2canvas, jsPDF) {
5353
var container = html2pdf.makeContainer(source, pageSize);
5454
var overlay = container.parentElement;
5555

56+
// Get the locations of all hyperlinks.
57+
if (opt.enableLinks) {
58+
var links = container.querySelectorAll('a');
59+
var containerRect = unitConvert(container.getBoundingClientRect(), pageSize.k);
60+
opt.links = Array.prototype.map.call(links, function(link) {
61+
var clientRect = unitConvert(link.getBoundingClientRect(), pageSize.k);
62+
clientRect.left -= containerRect.left;
63+
clientRect.top -= containerRect.top;
64+
return { el: link, clientRect: clientRect };
65+
});
66+
}
67+
5668
// Render the canvas and pass the result to makePDF.
5769
var onRendered = opt.html2canvas.onrendered || function() {};
5870
opt.html2canvas.onrendered = function(canvas) {
@@ -81,6 +93,7 @@ var html2pdf = (function(html2canvas, jsPDF) {
8193
opt.jsPDF = opt.jsPDF || {};
8294
opt.html2canvas = opt.html2canvas || {};
8395
opt.filename = opt.filename && objType(opt.filename) === 'string' ? opt.filename : 'file.pdf';
96+
opt.enableLinks = opt.hasOwnProperty('enableLinks') ? opt.enableLinks : true;
8497
opt.image = opt.image || {};
8598
opt.image.type = opt.image.type || 'jpeg';
8699
opt.image.quality = opt.image.quality || 0.95;
@@ -148,11 +161,11 @@ var html2pdf = (function(html2canvas, jsPDF) {
148161

149162
// Break the full canvas into pages, then reduce it to one page.
150163
var ctx = canvas.getContext('2d');
151-
var fullHeight = canvas.height;
152-
var pageHeight = Math.floor(canvas.width * pageSize.inner.ratio);
153-
var nPages = Math.ceil(fullHeight / pageHeight);
164+
var pxFullHeight = canvas.height;
165+
var pxPageHeight = Math.floor(canvas.width * pageSize.inner.ratio);
166+
var nPages = Math.ceil(pxFullHeight / pxPageHeight);
154167
var imgFull = ctx.getImageData(0, 0, canvas.width, canvas.height);
155-
canvas.height = pageHeight;
168+
canvas.height = pxPageHeight;
156169

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

166179
// Add the page to the PDF.
167180
if (page) pdf.addPage();
168181
var imgData = canvas.toDataURL('image/' + opt.image.type, opt.image.quality);
169182
pdf.addImage(imgData, opt.image.type, opt.margin[1], opt.margin[0],
170183
pageSize.inner.width, pageSize.inner.height);
184+
185+
// Add hyperlinks.
186+
if (opt.enableLinks) {
187+
var pageTop = page * pageSize.inner.height;
188+
opt.links.forEach(function(link) {
189+
if (link.clientRect.top > pageTop && link.clientRect.top < pageTop + pageSize.inner.height) {
190+
var left = opt.margin[1] + link.clientRect.left;
191+
var top = opt.margin[0] + link.clientRect.top - pageTop;
192+
pdf.link(left, top, link.clientRect.width, link.clientRect.height, { url: link.el.href });
193+
}
194+
});
195+
}
171196
}
172197

173198
// Finish the PDF.
@@ -199,6 +224,15 @@ var html2pdf = (function(html2canvas, jsPDF) {
199224
return el;
200225
};
201226

227+
// Convert units using the conversion value 'k' from jsPDF.
228+
var unitConvert = function(obj, k) {
229+
var newObj = {};
230+
for (var key in obj) {
231+
newObj[key] = obj[key] * 72 / 96 / k;
232+
}
233+
return newObj;
234+
};
235+
202236
// Get dimensions of a PDF page, as determined by jsPDF.
203237
jsPDF.getPageSize = function(orientation, unit, format) {
204238
// Decode options object

vendor/jspdf.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)