Skip to content

Commit 18c56bf

Browse files
Add 'width' and 'windowWidth' options to the html method (#3203)
Co-authored-by: Lukas Hollaender <[email protected]>
1 parent eb1326a commit 18c56bf

11 files changed

+115
-10
lines changed

src/modules/html.js

+28-8
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,16 @@ import { globalObject } from "../libs/globalObject.js";
320320
position: "relative",
321321
display: "inline-block",
322322
width:
323-
Math.max(
324-
this.prop.src.clientWidth,
325-
this.prop.src.scrollWidth,
326-
this.prop.src.offsetWidth
327-
) + "px",
323+
(typeof this.opt.width === "number" &&
324+
!isNaN(this.opt.width) &&
325+
typeof this.opt.windowWidth === "number" &&
326+
!isNaN(this.opt.windowWidth)
327+
? this.opt.windowWidth
328+
: Math.max(
329+
this.prop.src.clientWidth,
330+
this.prop.src.scrollWidth,
331+
this.prop.src.offsetWidth
332+
)) + "px",
328333
left: 0,
329334
right: 0,
330335
top: 0,
@@ -429,11 +434,20 @@ import { globalObject } from "../libs/globalObject.js";
429434

430435
var pdf = this.opt.jsPDF;
431436
var fontFaces = this.opt.fontFaces;
437+
438+
var scale =
439+
typeof this.opt.width === "number" &&
440+
!isNaN(this.opt.width) &&
441+
typeof this.opt.windowWidth === "number" &&
442+
!isNaN(this.opt.windowWidth)
443+
? this.opt.width / this.opt.windowWidth
444+
: 1;
445+
432446
var options = Object.assign(
433447
{
434448
async: true,
435449
allowTaint: true,
436-
scale: 1,
450+
scale: scale,
437451
scrollX: this.opt.scrollX || 0,
438452
scrollY: this.opt.scrollY || 0,
439453
backgroundColor: "#ffffff",
@@ -1011,8 +1025,14 @@ import { globalObject } from "../libs/globalObject.js";
10111025
* @param {Html2CanvasOptions} [options.html2canvas] html2canvas options
10121026
* @param {FontFace[]} [options.fontFaces] A list of font-faces to match when resolving fonts. Fonts will be added to the PDF based on the specified URL. If omitted, the font match algorithm falls back to old algorithm.
10131027
* @param {jsPDF} [options.jsPDF] jsPDF instance
1014-
* @param {number} [options.x] x position on the PDF document
1015-
* @param {number} [options.y] y position on the PDF document
1028+
* @param {number=} [options.x] x position on the PDF document in jsPDF units.
1029+
* @param {number=} [options.y] y position on the PDF document in jsPDF units.
1030+
* @param {number=} [options.width] The target width in the PDF document in jsPDF units. The rendered element will be
1031+
* scaled such that it fits into the specified width. Has no effect if either the <code>html2canvas.scale<code> is
1032+
* specified or the <code>windowWidth</code> option is NOT specified.
1033+
* @param {number=} [options.windowWidth] The window width in CSS pixels. In contrast to the
1034+
* <code>html2canvas.windowWidth</code> option, this option affects the actual container size while rendering and
1035+
* does NOT affect CSS media queries. This option only has an effect, if the <code>width<code> option is also specified.
10161036
*
10171037
* @example
10181038
* var doc = new jsPDF();
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

test/specs/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ If a reference PDF doesn't exist it will be created if you run this command
2020
while the tests run:
2121

2222
```
23-
node tests/utils/reference-server.js
23+
node test/utils/reference-server.js
2424
```
2525

2626
This generates and collects reference PDFs from real browsers. This should be

test/specs/html.spec.js

+84-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function toFontFaceRule(fontFace) {
2727
`;
2828
}
2929

30-
describe("Module: html", function() {
30+
describe("Module: html", () => {
3131
if (
3232
(typeof isNode != "undefined" && isNode) ||
3333
navigator.userAgent.indexOf("Chrome") < 0
@@ -41,6 +41,89 @@ describe("Module: html", function() {
4141
comparePdf(doc.output(), "html-basic.pdf", "html");
4242
});
4343

44+
it("respects width and windowWidth options", async () => {
45+
const markup =
46+
"<div>" +
47+
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet reprehenderit nihil natus magnam doloremque voluptate ab, laborum officiis corrupti eius voluptatibus quisquam illum esse corporis quod fugit quibusdam minima provident." +
48+
"</div>";
49+
50+
const doc210$250 = await render(markup, { width: 210, windowWidth: 250 });
51+
comparePdf(
52+
doc210$250.output(),
53+
"html-width-210-windowWidth-250.pdf",
54+
"html"
55+
);
56+
57+
const doc210$500 = await render(markup, { width: 210, windowWidth: 500 });
58+
comparePdf(
59+
doc210$500.output(),
60+
"html-width-210-windowWidth-500.pdf",
61+
"html"
62+
);
63+
64+
const doc210$1000 = await render(markup, { width: 210, windowWidth: 1000 });
65+
comparePdf(
66+
doc210$1000.output(),
67+
"html-width-210-windowWidth-1000.pdf",
68+
"html"
69+
);
70+
71+
const doc100$500 = await render(markup, { width: 100, windowWidth: 500 });
72+
comparePdf(
73+
doc100$500.output(),
74+
"html-width-100-windowWidth-500.pdf",
75+
"html"
76+
);
77+
78+
const doc300$500 = await render(markup, { width: 300, windowWidth: 500 });
79+
comparePdf(
80+
doc300$500.output(),
81+
"html-width-300-windowWidth-500.pdf",
82+
"html"
83+
);
84+
});
85+
86+
it("width should not overwrite user-provided html2canvas.scale option", async () => {
87+
const markup =
88+
"<div>" +
89+
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet reprehenderit nihil natus magnam doloremque voluptate ab, laborum officiis corrupti eius voluptatibus quisquam illum esse corporis quod fugit quibusdam minima provident." +
90+
"</div>";
91+
const doc = await render(markup, {
92+
width: 300,
93+
windowWidth: 500,
94+
html2canvas: { scale: 2 }
95+
});
96+
comparePdf(
97+
doc.output(),
98+
"html-width-300-windowWidth-500-scale-2.pdf",
99+
"html"
100+
);
101+
});
102+
103+
it("width and windowWidth should only have an effect if both are supplied", async () => {
104+
const markup =
105+
"<div>" +
106+
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet reprehenderit nihil natus magnam doloremque voluptate ab, laborum officiis corrupti eius voluptatibus quisquam illum esse corporis quod fugit quibusdam minima provident." +
107+
"</div>";
108+
const docWidthOnly = await render(markup, {
109+
width: 300
110+
});
111+
comparePdf(
112+
docWidthOnly.output(),
113+
"html-width-default-windowWidth-default.pdf",
114+
"html"
115+
);
116+
117+
const docWindowWidthOnly = await render(markup, {
118+
windowWidth: 500
119+
});
120+
comparePdf(
121+
docWindowWidthOnly.output(),
122+
"html-width-default-windowWidth-default.pdf",
123+
"html"
124+
);
125+
});
126+
44127
it("renders font-faces", async () => {
45128
const opts = {
46129
fontFaces: [

types/index.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ declare module "jspdf" {
229229
jsPDF?: jsPDF;
230230
x?: number;
231231
y?: number;
232+
width?: number;
233+
windowWidth?: number;
232234
fontFaces?: HTMLFontFace[];
233235
}
234236

0 commit comments

Comments
 (0)