jspdf-utils 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/html-to-pdf.d.ts +6 -13
- package/dist/html-to-pdf.js +157 -143
- package/package.json +1 -1
package/dist/html-to-pdf.d.ts
CHANGED
|
@@ -38,20 +38,13 @@ export interface PrepareResult {
|
|
|
38
38
|
/** Compute derived layout values from options. */
|
|
39
39
|
declare function computeLayout(container: HTMLElement, opts: PageOptions): Layout;
|
|
40
40
|
/**
|
|
41
|
-
* Clone an element
|
|
42
|
-
|
|
43
|
-
declare function createPrintClone(source: HTMLElement, pageWidth?: number): HTMLElement;
|
|
44
|
-
/**
|
|
45
|
-
* Reset framework/global CSS on table elements inside the clone so that
|
|
46
|
-
* jsPDF's doc.html() renderer produces consistent output regardless of
|
|
47
|
-
* the host page's CSS environment (e.g. Tailwind preflight, CSS resets).
|
|
41
|
+
* Clone an element into a hidden iframe so that the page's CSS frameworks
|
|
42
|
+
* (Tailwind, Bootstrap, etc.) cannot interfere with PDF rendering.
|
|
48
43
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* Returns a cleanup function that removes the injected style element.
|
|
44
|
+
* Only @font-face rules are copied into the iframe so custom fonts still work.
|
|
45
|
+
* The returned element's `.remove()` method cleans up the iframe automatically.
|
|
53
46
|
*/
|
|
54
|
-
declare function
|
|
47
|
+
declare function createPrintClone(source: HTMLElement, pageWidth?: number): HTMLElement;
|
|
55
48
|
/**
|
|
56
49
|
* Convert HTML table attributes (cellpadding, cellspacing, border) to
|
|
57
50
|
* inline CSS so doc.html()'s renderer picks them up.
|
|
@@ -92,4 +85,4 @@ export interface ImagePDFOptions {
|
|
|
92
85
|
* screenshot — no selectable or extractable text in the output.
|
|
93
86
|
*/
|
|
94
87
|
declare function renderImagePDF(source: HTMLElement, opts?: Partial<PageOptions> & ImagePDFOptions): Promise<jsPDF>;
|
|
95
|
-
export { PAGE_SIZES, PAGE_MARGINS, computeLayout, createPrintClone,
|
|
88
|
+
export { PAGE_SIZES, PAGE_MARGINS, computeLayout, createPrintClone, normalizeTableAttributes, splitOversizedTables, splitOversizedText, insertPageBreakSpacers, prepare, renderHTML, renderImagePDF, };
|
package/dist/html-to-pdf.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import D from "html2canvas";
|
|
2
2
|
const N = {
|
|
3
3
|
a0: [841, 1189],
|
|
4
4
|
a1: [594, 841],
|
|
@@ -10,7 +10,7 @@ const N = {
|
|
|
10
10
|
letter: [215.9, 279.4],
|
|
11
11
|
legal: [215.9, 355.6],
|
|
12
12
|
tabloid: [279.4, 431.8]
|
|
13
|
-
},
|
|
13
|
+
}, R = {
|
|
14
14
|
a0: 40,
|
|
15
15
|
a1: 35,
|
|
16
16
|
a2: 30,
|
|
@@ -22,214 +22,228 @@ const N = {
|
|
|
22
22
|
legal: 25.4,
|
|
23
23
|
tabloid: 25
|
|
24
24
|
};
|
|
25
|
-
function
|
|
26
|
-
const
|
|
25
|
+
function x(r = {}) {
|
|
26
|
+
const n = r.format ?? "a4", [i, e] = N[n], o = r.pageWidth ?? i, t = r.pageHeight ?? e, a = R[n], c = {
|
|
27
27
|
top: a,
|
|
28
28
|
right: a,
|
|
29
29
|
bottom: a,
|
|
30
30
|
left: a
|
|
31
31
|
};
|
|
32
32
|
return {
|
|
33
|
-
unit:
|
|
34
|
-
format:
|
|
35
|
-
pageWidth:
|
|
36
|
-
pageHeight:
|
|
37
|
-
margin: { ...c, ...
|
|
33
|
+
unit: r.unit ?? "mm",
|
|
34
|
+
format: n,
|
|
35
|
+
pageWidth: o,
|
|
36
|
+
pageHeight: t,
|
|
37
|
+
margin: { ...c, ...r.margin }
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
-
function
|
|
41
|
-
const
|
|
42
|
-
return { renderedWidth:
|
|
40
|
+
function C(r, n) {
|
|
41
|
+
const i = r.offsetWidth, e = n.pageWidth - n.margin.left - n.margin.right, o = e / i, a = (n.pageHeight - n.margin.top - n.margin.bottom) / o;
|
|
42
|
+
return { renderedWidth: i, scale: o, contentWidthMm: e, pageContentPx: a };
|
|
43
43
|
}
|
|
44
|
-
function v(
|
|
45
|
-
const
|
|
46
|
-
|
|
44
|
+
function v(r, n = 210) {
|
|
45
|
+
const i = document.createElement("iframe");
|
|
46
|
+
Object.assign(i.style, {
|
|
47
47
|
position: "fixed",
|
|
48
48
|
top: "0",
|
|
49
|
-
left: "
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
left: "-99999px",
|
|
50
|
+
width: n + "mm",
|
|
51
|
+
height: "99999px",
|
|
52
|
+
border: "none",
|
|
52
53
|
opacity: "0.000001",
|
|
53
54
|
pointerEvents: "none"
|
|
54
|
-
}), document.body.appendChild(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const o = "
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
55
|
+
}), document.body.appendChild(i);
|
|
56
|
+
const e = i.contentDocument;
|
|
57
|
+
if (!e) throw new Error("Could not access iframe document");
|
|
58
|
+
const o = e.createElement("base");
|
|
59
|
+
o.href = document.baseURI, e.head.appendChild(o);
|
|
60
|
+
const t = [];
|
|
61
|
+
for (const c of document.styleSheets)
|
|
62
|
+
try {
|
|
63
|
+
for (const l of c.cssRules)
|
|
64
|
+
l instanceof CSSFontFaceRule && t.push(l.cssText);
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
if (t.length > 0) {
|
|
68
|
+
const c = e.createElement("style");
|
|
69
|
+
c.textContent = t.join(`
|
|
70
|
+
`), e.head.appendChild(c);
|
|
71
|
+
}
|
|
72
|
+
const a = r.cloneNode(!0);
|
|
73
|
+
return Object.assign(a.style, {
|
|
74
|
+
boxSizing: "border-box",
|
|
75
|
+
width: n + "mm"
|
|
76
|
+
}), e.body.style.margin = "0", e.body.appendChild(a), a.remove = () => i.remove(), a;
|
|
61
77
|
}
|
|
62
|
-
function A(
|
|
63
|
-
for (const
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
66
|
-
for (const
|
|
67
|
-
|
|
68
|
-
|
|
78
|
+
function A(r) {
|
|
79
|
+
for (const n of r.querySelectorAll("table")) {
|
|
80
|
+
const i = n.getAttribute("cellpadding");
|
|
81
|
+
if (i) {
|
|
82
|
+
for (const e of n.querySelectorAll("th, td"))
|
|
83
|
+
e.style.padding || (e.style.padding = i + "px");
|
|
84
|
+
n.removeAttribute("cellpadding");
|
|
69
85
|
}
|
|
70
86
|
}
|
|
71
87
|
}
|
|
72
|
-
function
|
|
73
|
-
for (const
|
|
74
|
-
|
|
88
|
+
function E(r, n) {
|
|
89
|
+
for (const i of Array.from(
|
|
90
|
+
r.querySelectorAll(":scope > table")
|
|
75
91
|
)) {
|
|
76
|
-
if (
|
|
77
|
-
const
|
|
78
|
-
if (
|
|
79
|
-
const
|
|
80
|
-
let
|
|
81
|
-
for (const
|
|
82
|
-
const g =
|
|
83
|
-
|
|
92
|
+
if (i.offsetHeight <= n) continue;
|
|
93
|
+
const e = Array.from(i.rows);
|
|
94
|
+
if (e.length === 0) continue;
|
|
95
|
+
const o = e[0].querySelector("th") !== null, t = o ? e[0] : null, a = o ? e.slice(1) : e, c = t ? t.offsetHeight : 0, l = n - c - 2, d = [];
|
|
96
|
+
let f = [], h = 0;
|
|
97
|
+
for (const s of a) {
|
|
98
|
+
const g = s.offsetHeight;
|
|
99
|
+
h + g > l && f.length > 0 && (d.push(f), f = [], h = 0), f.push(s), h += g;
|
|
84
100
|
}
|
|
85
|
-
|
|
86
|
-
for (const
|
|
87
|
-
const g =
|
|
88
|
-
|
|
89
|
-
for (const m of
|
|
90
|
-
|
|
101
|
+
f.length > 0 && d.push(f);
|
|
102
|
+
for (const s of d) {
|
|
103
|
+
const g = i.cloneNode(!1);
|
|
104
|
+
t && g.appendChild(t.cloneNode(!0));
|
|
105
|
+
for (const m of s) g.appendChild(m.cloneNode(!0));
|
|
106
|
+
i.parentNode.insertBefore(g, i);
|
|
91
107
|
}
|
|
92
|
-
|
|
108
|
+
i.remove();
|
|
93
109
|
}
|
|
94
110
|
}
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
111
|
+
function P(r, n) {
|
|
112
|
+
const i = r.ownerDocument;
|
|
113
|
+
for (const e of Array.from(r.querySelectorAll(":scope > *"))) {
|
|
114
|
+
const o = e;
|
|
115
|
+
if (o.offsetHeight <= n || o.tagName === "TABLE")
|
|
99
116
|
continue;
|
|
100
|
-
const
|
|
101
|
-
d.setAttribute("style",
|
|
117
|
+
const t = o.tagName, a = o.getAttribute("style") || "", c = i.defaultView.getComputedStyle(o).width, l = (o.textContent || "").split(/\s+/).filter(Boolean), d = i.createElement(t);
|
|
118
|
+
d.setAttribute("style", a), Object.assign(d.style, {
|
|
102
119
|
position: "absolute",
|
|
103
120
|
visibility: "hidden",
|
|
104
|
-
width:
|
|
105
|
-
}),
|
|
106
|
-
const
|
|
107
|
-
let
|
|
108
|
-
for (;
|
|
109
|
-
let
|
|
110
|
-
for (;
|
|
111
|
-
const
|
|
112
|
-
d.textContent =
|
|
121
|
+
width: c
|
|
122
|
+
}), r.appendChild(d);
|
|
123
|
+
const f = [];
|
|
124
|
+
let h = 0;
|
|
125
|
+
for (; h < l.length; ) {
|
|
126
|
+
let s = h + 1, g = l.length;
|
|
127
|
+
for (; s < g; ) {
|
|
128
|
+
const u = Math.ceil((s + g) / 2);
|
|
129
|
+
d.textContent = l.slice(h, u).join(" "), d.offsetHeight <= n ? s = u : g = u - 1;
|
|
113
130
|
}
|
|
114
|
-
const
|
|
115
|
-
|
|
131
|
+
const m = i.createElement(t);
|
|
132
|
+
m.setAttribute("style", a), m.textContent = l.slice(h, s).join(" "), f.push(m), h = s;
|
|
116
133
|
}
|
|
117
134
|
d.remove();
|
|
118
|
-
for (const
|
|
119
|
-
|
|
120
|
-
|
|
135
|
+
for (const s of f)
|
|
136
|
+
o.parentNode.insertBefore(s, o);
|
|
137
|
+
o.remove();
|
|
121
138
|
}
|
|
122
139
|
}
|
|
123
|
-
function
|
|
124
|
-
const
|
|
125
|
-
for (const
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
const
|
|
129
|
-
|
|
140
|
+
function W(r, n) {
|
|
141
|
+
const i = r.ownerDocument, e = Array.from(r.children);
|
|
142
|
+
for (const o of e) {
|
|
143
|
+
const t = o.offsetTop, a = t + o.offsetHeight, c = (Math.floor(t / n) + 1) * n;
|
|
144
|
+
if (a > c && o.offsetHeight <= n) {
|
|
145
|
+
const l = i.createElement("div");
|
|
146
|
+
l.style.height = c - t + 1 + "px", o.parentNode.insertBefore(l, o);
|
|
130
147
|
}
|
|
131
148
|
}
|
|
132
149
|
}
|
|
133
|
-
function
|
|
134
|
-
const
|
|
135
|
-
A(
|
|
136
|
-
const
|
|
137
|
-
return
|
|
138
|
-
clone:
|
|
139
|
-
layout:
|
|
140
|
-
options:
|
|
141
|
-
cleanup: () =>
|
|
142
|
-
r(), t.remove();
|
|
143
|
-
}
|
|
150
|
+
function T(r, n = {}) {
|
|
151
|
+
const i = x(n), e = v(r, i.pageWidth);
|
|
152
|
+
A(e);
|
|
153
|
+
const o = C(e, i);
|
|
154
|
+
return E(e, o.pageContentPx), P(e, o.pageContentPx), W(e, o.pageContentPx), {
|
|
155
|
+
clone: e,
|
|
156
|
+
layout: o,
|
|
157
|
+
options: i,
|
|
158
|
+
cleanup: () => e.remove()
|
|
144
159
|
};
|
|
145
160
|
}
|
|
146
|
-
async function
|
|
147
|
-
const { clone:
|
|
161
|
+
async function F(r, n, i = {}) {
|
|
162
|
+
const { clone: e, layout: o, options: t, cleanup: a } = T(n, i);
|
|
148
163
|
try {
|
|
149
164
|
await new Promise((c) => {
|
|
150
|
-
|
|
165
|
+
r.html(e, {
|
|
151
166
|
callback: () => c(),
|
|
152
|
-
width:
|
|
153
|
-
windowWidth:
|
|
167
|
+
width: o.contentWidthMm,
|
|
168
|
+
windowWidth: o.renderedWidth,
|
|
154
169
|
margin: [
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
170
|
+
t.margin.top,
|
|
171
|
+
t.margin.right,
|
|
172
|
+
t.margin.bottom,
|
|
173
|
+
t.margin.left
|
|
159
174
|
]
|
|
160
175
|
});
|
|
161
176
|
});
|
|
162
177
|
} finally {
|
|
163
178
|
a();
|
|
164
179
|
}
|
|
165
|
-
return
|
|
180
|
+
return r;
|
|
166
181
|
}
|
|
167
|
-
async function
|
|
168
|
-
const { imageFormat:
|
|
169
|
-
|
|
170
|
-
const c =
|
|
171
|
-
|
|
182
|
+
async function B(r, n = {}) {
|
|
183
|
+
const { imageFormat: i = "JPEG", imageQuality: e = 1, scale: o = 2 } = n, t = x(n), a = v(r, t.pageWidth);
|
|
184
|
+
A(a);
|
|
185
|
+
const c = C(a, t);
|
|
186
|
+
E(a, c.pageContentPx), P(a, c.pageContentPx), W(a, c.pageContentPx);
|
|
172
187
|
try {
|
|
173
|
-
const
|
|
174
|
-
scale:
|
|
188
|
+
const l = await D(a, {
|
|
189
|
+
scale: o,
|
|
175
190
|
backgroundColor: "#ffffff"
|
|
176
|
-
}), { jsPDF:
|
|
177
|
-
orientation:
|
|
191
|
+
}), { jsPDF: d } = await import("jspdf"), f = t.pageWidth - t.margin.left - t.margin.right, h = t.pageHeight - t.margin.top - t.margin.bottom, s = l.width, g = h / f * s, m = Math.ceil(l.height / g), u = t.pageWidth > t.pageHeight ? "l" : "p", H = new d({
|
|
192
|
+
orientation: u,
|
|
178
193
|
unit: "mm",
|
|
179
|
-
format: [
|
|
194
|
+
format: [t.pageWidth, t.pageHeight]
|
|
180
195
|
});
|
|
181
|
-
for (let
|
|
182
|
-
const
|
|
196
|
+
for (let p = 0; p < m; p++) {
|
|
197
|
+
const y = Math.min(
|
|
183
198
|
g,
|
|
184
|
-
|
|
185
|
-
),
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
if (!
|
|
189
|
-
|
|
190
|
-
d,
|
|
191
|
-
0,
|
|
192
|
-
u * g,
|
|
199
|
+
l.height - p * g
|
|
200
|
+
), b = document.createElement("canvas");
|
|
201
|
+
b.width = s, b.height = y;
|
|
202
|
+
const w = b.getContext("2d");
|
|
203
|
+
if (!w) throw new Error("Could not get canvas context");
|
|
204
|
+
w.fillStyle = "#ffffff", w.fillRect(0, 0, s, y), w.drawImage(
|
|
193
205
|
l,
|
|
194
|
-
p,
|
|
195
206
|
0,
|
|
207
|
+
p * g,
|
|
208
|
+
s,
|
|
209
|
+
y,
|
|
196
210
|
0,
|
|
197
|
-
|
|
198
|
-
|
|
211
|
+
0,
|
|
212
|
+
s,
|
|
213
|
+
y
|
|
199
214
|
);
|
|
200
|
-
const
|
|
201
|
-
`image/${
|
|
202
|
-
|
|
215
|
+
const S = b.toDataURL(
|
|
216
|
+
`image/${i.toLowerCase()}`,
|
|
217
|
+
e
|
|
203
218
|
);
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
219
|
+
p > 0 && H.addPage([t.pageWidth, t.pageHeight], u);
|
|
220
|
+
const M = y / s * f;
|
|
221
|
+
H.addImage(
|
|
222
|
+
S,
|
|
223
|
+
i,
|
|
224
|
+
t.margin.left,
|
|
225
|
+
t.margin.top,
|
|
226
|
+
f,
|
|
207
227
|
M,
|
|
208
|
-
n,
|
|
209
|
-
e.margin.left,
|
|
210
|
-
e.margin.top,
|
|
211
|
-
s,
|
|
212
|
-
E,
|
|
213
228
|
void 0,
|
|
214
229
|
"FAST"
|
|
215
230
|
);
|
|
216
231
|
}
|
|
217
|
-
return
|
|
232
|
+
return H;
|
|
218
233
|
} finally {
|
|
219
234
|
a.remove();
|
|
220
235
|
}
|
|
221
236
|
}
|
|
222
237
|
export {
|
|
223
|
-
|
|
238
|
+
R as PAGE_MARGINS,
|
|
224
239
|
N as PAGE_SIZES,
|
|
225
|
-
|
|
240
|
+
C as computeLayout,
|
|
226
241
|
v as createPrintClone,
|
|
227
|
-
|
|
242
|
+
W as insertPageBreakSpacers,
|
|
228
243
|
A as normalizeTableAttributes,
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
W as splitOversizedText
|
|
244
|
+
T as prepare,
|
|
245
|
+
F as renderHTML,
|
|
246
|
+
B as renderImagePDF,
|
|
247
|
+
E as splitOversizedTables,
|
|
248
|
+
P as splitOversizedText
|
|
235
249
|
};
|
package/package.json
CHANGED