jspdf-utils 0.1.5 → 0.1.7

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.
@@ -81,4 +81,15 @@ export interface ImagePDFOptions {
81
81
  * screenshot — no selectable or extractable text in the output.
82
82
  */
83
83
  declare function renderImagePDF(source: HTMLElement, opts?: Partial<PageOptions> & ImagePDFOptions): Promise<jsPDF>;
84
- export { PAGE_SIZES, PAGE_MARGINS, computeLayout, createPrintClone, normalizeTableAttributes, splitOversizedTables, splitOversizedText, insertPageBreakSpacers, prepare, renderHTML, renderImagePDF, };
84
+ /**
85
+ * Render an HTML element to an array of page images (data URLs).
86
+ * Each image represents a full page with margins, matching the
87
+ * visual output of renderImagePDF.
88
+ */
89
+ declare function renderPageImages(source: HTMLElement, opts?: Partial<PageOptions> & ImagePDFOptions): Promise<string[]>;
90
+ /**
91
+ * Render an HTML element as page images and inject them into a scrollable
92
+ * container. Each image is sized to match the page format dimensions.
93
+ */
94
+ declare function previewPageImages(source: HTMLElement, container: HTMLElement, opts?: Partial<PageOptions> & ImagePDFOptions): Promise<void>;
95
+ export { PAGE_SIZES, PAGE_MARGINS, computeLayout, createPrintClone, normalizeTableAttributes, splitOversizedTables, splitOversizedText, insertPageBreakSpacers, prepare, renderHTML, renderImagePDF, renderPageImages, previewPageImages, };
@@ -1,5 +1,5 @@
1
- import N from "html2canvas";
2
- const T = {
1
+ import T from "html2canvas";
2
+ const k = {
3
3
  a0: [841, 1189],
4
4
  a1: [594, 841],
5
5
  a2: [420, 594],
@@ -10,7 +10,7 @@ const T = {
10
10
  letter: [215.9, 279.4],
11
11
  legal: [215.9, 355.6],
12
12
  tabloid: [279.4, 431.8]
13
- }, B = {
13
+ }, L = {
14
14
  a0: 40,
15
15
  a1: 35,
16
16
  a2: 30,
@@ -22,205 +22,276 @@ const T = {
22
22
  legal: 25.4,
23
23
  tabloid: 25
24
24
  };
25
- function x(i = {}) {
26
- const o = i.format ?? "a4", [n, t] = T[o], r = i.pageWidth ?? n, e = i.pageHeight ?? t, a = B[o], c = {
27
- top: a,
28
- right: a,
29
- bottom: a,
30
- left: a
25
+ function W(i = {}) {
26
+ const e = i.format ?? "a4", [o, n] = k[e], r = i.pageWidth ?? o, t = i.pageHeight ?? n, c = L[e], a = {
27
+ top: c,
28
+ right: c,
29
+ bottom: c,
30
+ left: c
31
31
  };
32
32
  return {
33
33
  unit: i.unit ?? "mm",
34
- format: o,
34
+ format: e,
35
35
  pageWidth: r,
36
- pageHeight: e,
37
- margin: { ...c, ...i.margin }
36
+ pageHeight: t,
37
+ margin: { ...a, ...i.margin }
38
38
  };
39
39
  }
40
- function A(i, o) {
41
- const n = i.offsetWidth, t = o.pageWidth - o.margin.left - o.margin.right, r = t / n, a = (o.pageHeight - o.margin.top - o.margin.bottom) / r;
42
- return { renderedWidth: n, scale: r, contentWidthMm: t, pageContentPx: a };
40
+ function M(i, e) {
41
+ const o = i.offsetWidth, n = e.pageWidth - e.margin.left - e.margin.right, r = n / o, c = (e.pageHeight - e.margin.top - e.margin.bottom) / r;
42
+ return { renderedWidth: o, scale: r, contentWidthMm: n, pageContentPx: c };
43
43
  }
44
- function v(i, o = 210) {
45
- const n = i.cloneNode(!0);
46
- return Object.assign(n.style, {
44
+ function A(i, e = 210) {
45
+ const o = i.cloneNode(!0);
46
+ return Object.assign(o.style, {
47
47
  position: "fixed",
48
48
  top: "0",
49
49
  left: "0",
50
50
  boxSizing: "border-box",
51
- width: o + "mm",
51
+ width: e + "mm",
52
52
  opacity: "0.000001",
53
53
  pointerEvents: "none"
54
- }), document.body.appendChild(n), n;
54
+ }), document.body.appendChild(o), o;
55
55
  }
56
- function W(i) {
57
- for (const o of i.querySelectorAll("table")) {
58
- const n = o.getAttribute("cellpadding");
59
- if (n) {
60
- for (const t of o.querySelectorAll("th, td"))
61
- t.style.padding || (t.style.padding = n + "px");
62
- o.removeAttribute("cellpadding");
56
+ function S() {
57
+ const i = document.createElement("style");
58
+ return i.setAttribute("data-jspdf-utils", ""), i.textContent = "img { display: inline !important; }", document.head.appendChild(i), () => i.remove();
59
+ }
60
+ function E(i) {
61
+ for (const e of i.querySelectorAll("table")) {
62
+ const o = e.getAttribute("cellpadding");
63
+ if (o) {
64
+ for (const n of e.querySelectorAll("th, td"))
65
+ n.style.padding || (n.style.padding = o + "px");
66
+ e.removeAttribute("cellpadding");
63
67
  }
64
68
  }
65
69
  }
66
- function C(i, o) {
67
- for (const n of Array.from(
70
+ function R(i, e) {
71
+ for (const o of Array.from(
68
72
  i.querySelectorAll(":scope > table")
69
73
  )) {
70
- if (n.offsetHeight <= o) continue;
71
- const t = Array.from(n.rows);
72
- if (t.length === 0) continue;
73
- const r = t[0].querySelector("th") !== null, e = r ? t[0] : null, a = r ? t.slice(1) : t, c = e ? e.offsetHeight : 0, f = o - c - 2, h = [];
74
- let l = [], d = 0;
75
- for (const s of a) {
76
- const g = s.offsetHeight;
77
- d + g > f && l.length > 0 && (h.push(l), l = [], d = 0), l.push(s), d += g;
74
+ if (o.offsetHeight <= e) continue;
75
+ const n = Array.from(o.rows);
76
+ if (n.length === 0) continue;
77
+ const r = n[0].querySelector("th") !== null, t = r ? n[0] : null, c = r ? n.slice(1) : n, a = t ? t.offsetHeight : 0, h = e - a - 2, d = [];
78
+ let l = [], g = 0;
79
+ for (const m of c) {
80
+ const s = m.offsetHeight;
81
+ g + s > h && l.length > 0 && (d.push(l), l = [], g = 0), l.push(m), g += s;
78
82
  }
79
- l.length > 0 && h.push(l);
80
- for (const s of h) {
81
- const g = n.cloneNode(!1);
82
- e && g.appendChild(e.cloneNode(!0));
83
- for (const m of s) g.appendChild(m.cloneNode(!0));
84
- n.parentNode.insertBefore(g, n);
83
+ l.length > 0 && d.push(l);
84
+ for (const m of d) {
85
+ const s = o.cloneNode(!1);
86
+ t && s.appendChild(t.cloneNode(!0));
87
+ for (const f of m) s.appendChild(f.cloneNode(!0));
88
+ o.parentNode.insertBefore(s, o);
85
89
  }
86
- n.remove();
90
+ o.remove();
87
91
  }
88
92
  }
89
- function P(i, o) {
90
- for (const n of Array.from(i.querySelectorAll(":scope > *"))) {
91
- const t = n;
92
- if (t.offsetHeight <= o || t.tagName === "TABLE")
93
+ function N(i, e) {
94
+ for (const o of Array.from(i.querySelectorAll(":scope > *"))) {
95
+ const n = o;
96
+ if (n.offsetHeight <= e || n.tagName === "TABLE")
93
97
  continue;
94
- const r = t.tagName, e = t.getAttribute("style") || "", a = getComputedStyle(t).width, c = (t.textContent || "").split(/\s+/).filter(Boolean), f = document.createElement(r);
95
- f.setAttribute("style", e), Object.assign(f.style, {
98
+ const r = n.tagName, t = n.getAttribute("style") || "", c = getComputedStyle(n).width, a = (n.textContent || "").split(/\s+/).filter(Boolean), h = document.createElement(r);
99
+ h.setAttribute("style", t), Object.assign(h.style, {
96
100
  position: "absolute",
97
101
  visibility: "hidden",
98
- width: a
99
- }), i.appendChild(f);
100
- const h = [];
102
+ width: c
103
+ }), i.appendChild(h);
104
+ const d = [];
101
105
  let l = 0;
102
- for (; l < c.length; ) {
103
- let d = l + 1, s = c.length;
104
- for (; d < s; ) {
105
- const m = Math.ceil((d + s) / 2);
106
- f.textContent = c.slice(l, m).join(" "), f.offsetHeight <= o ? d = m : s = m - 1;
106
+ for (; l < a.length; ) {
107
+ let g = l + 1, m = a.length;
108
+ for (; g < m; ) {
109
+ const f = Math.ceil((g + m) / 2);
110
+ h.textContent = a.slice(l, f).join(" "), h.offsetHeight <= e ? g = f : m = f - 1;
107
111
  }
108
- const g = document.createElement(r);
109
- g.setAttribute("style", e), g.textContent = c.slice(l, d).join(" "), h.push(g), l = d;
112
+ const s = document.createElement(r);
113
+ s.setAttribute("style", t), s.textContent = a.slice(l, g).join(" "), d.push(s), l = g;
110
114
  }
111
- f.remove();
112
- for (const d of h)
113
- t.parentNode.insertBefore(d, t);
114
- t.remove();
115
+ h.remove();
116
+ for (const g of d)
117
+ n.parentNode.insertBefore(g, n);
118
+ n.remove();
115
119
  }
116
120
  }
117
- function M(i, o) {
118
- const n = Array.from(i.children);
119
- for (const t of n) {
120
- const r = t.offsetTop, e = r + t.offsetHeight, a = (Math.floor(r / o) + 1) * o;
121
- if (e > a && t.offsetHeight <= o) {
122
- const c = document.createElement("div");
123
- c.style.height = a - r + 1 + "px", t.parentNode.insertBefore(c, t);
121
+ function j(i, e) {
122
+ const o = Array.from(i.children);
123
+ for (const n of o) {
124
+ const r = n.offsetTop, t = r + n.offsetHeight, c = (Math.floor(r / e) + 1) * e;
125
+ if (t > c && n.offsetHeight <= e) {
126
+ const a = document.createElement("div");
127
+ a.style.height = c - r + 1 + "px", n.parentNode.insertBefore(a, n);
124
128
  }
125
129
  }
126
130
  }
127
- function j(i, o = {}) {
128
- const n = x(o), t = v(i, n.pageWidth);
129
- W(t);
130
- const r = A(t, n);
131
- return C(t, r.pageContentPx), P(t, r.pageContentPx), M(t, r.pageContentPx), {
132
- clone: t,
133
- layout: r,
134
- options: n,
135
- cleanup: () => t.remove()
131
+ function B(i, e = {}) {
132
+ const o = W(e), n = S(), r = A(i, o.pageWidth);
133
+ E(r);
134
+ const t = M(r, o);
135
+ return R(r, t.pageContentPx), N(r, t.pageContentPx), j(r, t.pageContentPx), {
136
+ clone: r,
137
+ layout: t,
138
+ options: o,
139
+ cleanup: () => {
140
+ r.remove(), n();
141
+ }
136
142
  };
137
143
  }
138
- async function D(i, o, n = {}) {
139
- const { clone: t, layout: r, options: e, cleanup: a } = j(o, n);
144
+ async function D(i, e, o = {}) {
145
+ const { clone: n, layout: r, options: t, cleanup: c } = B(e, o);
140
146
  try {
141
- await new Promise((c) => {
142
- i.html(t, {
143
- callback: () => c(),
147
+ await new Promise((a) => {
148
+ i.html(n, {
149
+ callback: () => a(),
144
150
  width: r.contentWidthMm,
145
151
  windowWidth: r.renderedWidth,
146
152
  margin: [
147
- e.margin.top,
148
- e.margin.right,
149
- e.margin.bottom,
150
- e.margin.left
153
+ t.margin.top,
154
+ t.margin.right,
155
+ t.margin.bottom,
156
+ t.margin.left
151
157
  ]
152
158
  });
153
159
  });
154
160
  } finally {
155
- a();
161
+ c();
156
162
  }
157
163
  return i;
158
164
  }
159
- async function F(i, o = {}) {
160
- const { imageFormat: n = "JPEG", imageQuality: t = 1, scale: r = 2 } = o, e = x(o), a = v(i, e.pageWidth);
161
- a.style.opacity = "1", a.style.left = "-99999px", W(a);
162
- const c = A(a, e);
163
- C(a, c.pageContentPx), P(a, c.pageContentPx), M(a, c.pageContentPx);
165
+ async function F(i, e = {}) {
166
+ const { imageFormat: o = "JPEG", imageQuality: n = 1, scale: r = 2 } = e, t = W(e), c = S(), a = A(i, t.pageWidth);
167
+ a.style.opacity = "1", a.style.left = "-99999px", E(a);
168
+ const h = M(a, t);
169
+ R(a, h.pageContentPx), N(a, h.pageContentPx), j(a, h.pageContentPx);
164
170
  try {
165
- const f = await N(a, {
171
+ const d = await T(a, {
166
172
  scale: r,
167
173
  backgroundColor: "#ffffff"
168
- }), { jsPDF: h } = await import("jspdf"), l = e.pageWidth - e.margin.left - e.margin.right, d = e.pageHeight - e.margin.top - e.margin.bottom, s = f.width, g = d / l * s, m = Math.ceil(f.height / g), H = e.pageWidth > e.pageHeight ? "l" : "p", w = new h({
169
- orientation: H,
174
+ }), { jsPDF: l } = await import("jspdf"), g = t.pageWidth - t.margin.left - t.margin.right, m = t.pageHeight - t.margin.top - t.margin.bottom, s = d.width, f = m / g * s, P = Math.ceil(d.height / f), w = t.pageWidth > t.pageHeight ? "l" : "p", H = new l({
175
+ orientation: w,
170
176
  unit: "mm",
171
- format: [e.pageWidth, e.pageHeight]
177
+ format: [t.pageWidth, t.pageHeight]
172
178
  });
173
- for (let u = 0; u < m; u++) {
174
- const p = Math.min(
175
- g,
176
- f.height - u * g
177
- ), y = document.createElement("canvas");
178
- y.width = s, y.height = p;
179
- const b = y.getContext("2d");
180
- if (!b) throw new Error("Could not get canvas context");
181
- b.fillStyle = "#ffffff", b.fillRect(0, 0, s, p), b.drawImage(
179
+ for (let u = 0; u < P; u++) {
180
+ const y = Math.min(
182
181
  f,
182
+ d.height - u * f
183
+ ), b = document.createElement("canvas");
184
+ b.width = s, b.height = y;
185
+ const p = b.getContext("2d");
186
+ if (!p) throw new Error("Could not get canvas context");
187
+ p.fillStyle = "#ffffff", p.fillRect(0, 0, s, y), p.drawImage(
188
+ d,
183
189
  0,
184
- u * g,
190
+ u * f,
185
191
  s,
186
- p,
192
+ y,
187
193
  0,
188
194
  0,
189
195
  s,
190
- p
196
+ y
191
197
  );
192
- const E = y.toDataURL(
193
- `image/${n.toLowerCase()}`,
194
- t
198
+ const v = b.toDataURL(
199
+ `image/${o.toLowerCase()}`,
200
+ n
195
201
  );
196
- u > 0 && w.addPage([e.pageWidth, e.pageHeight], H);
197
- const S = p / s * l;
198
- w.addImage(
199
- E,
200
- n,
201
- e.margin.left,
202
- e.margin.top,
203
- l,
204
- S,
202
+ u > 0 && H.addPage([t.pageWidth, t.pageHeight], w);
203
+ const x = y / s * g;
204
+ H.addImage(
205
+ v,
206
+ o,
207
+ t.margin.left,
208
+ t.margin.top,
209
+ g,
210
+ x,
205
211
  void 0,
206
212
  "FAST"
207
213
  );
208
214
  }
209
- return w;
215
+ return H;
216
+ } finally {
217
+ a.remove(), c();
218
+ }
219
+ }
220
+ async function I(i, e = {}) {
221
+ const { imageFormat: o = "PNG", imageQuality: n = 1, scale: r = 2 } = e, t = W(e), c = S(), a = A(i, t.pageWidth);
222
+ a.style.opacity = "1", a.style.left = "-99999px", E(a);
223
+ const h = M(a, t);
224
+ R(a, h.pageContentPx), N(a, h.pageContentPx), j(a, h.pageContentPx);
225
+ try {
226
+ const d = await T(a, {
227
+ scale: r,
228
+ backgroundColor: "#ffffff"
229
+ }), l = t.pageWidth - t.margin.left - t.margin.right, g = t.pageHeight - t.margin.top - t.margin.bottom, m = d.width, s = g / l * m, f = m / l, P = Math.round(t.pageWidth * f), w = Math.round(t.pageHeight * f), H = Math.round(t.margin.top * f), u = Math.round(t.margin.left * f), y = Math.ceil(d.height / s), b = [];
230
+ for (let p = 0; p < y; p++) {
231
+ const v = Math.min(
232
+ s,
233
+ d.height - p * s
234
+ ), x = document.createElement("canvas");
235
+ x.width = P, x.height = w;
236
+ const C = x.getContext("2d");
237
+ if (!C) throw new Error("Could not get canvas context");
238
+ C.fillStyle = "#ffffff", C.fillRect(0, 0, P, w), C.drawImage(
239
+ d,
240
+ 0,
241
+ p * s,
242
+ m,
243
+ v,
244
+ u,
245
+ H,
246
+ m,
247
+ v
248
+ ), b.push(
249
+ x.toDataURL(
250
+ `image/${o.toLowerCase()}`,
251
+ n
252
+ )
253
+ );
254
+ }
255
+ return b;
210
256
  } finally {
211
- a.remove();
257
+ a.remove(), c();
258
+ }
259
+ }
260
+ async function q(i, e, o = {}) {
261
+ const n = W(o), r = await I(i, o);
262
+ e.innerHTML = "", Object.assign(e.style, {
263
+ width: "fit-content",
264
+ height: n.pageHeight + "mm",
265
+ maxHeight: "100vh",
266
+ overflowY: "auto",
267
+ background: "#e0e0e0"
268
+ });
269
+ for (let t = 0; t < r.length; t++) {
270
+ const c = document.createElement("img");
271
+ c.src = r[t], c.alt = `Page ${t + 1}`, Object.assign(c.style, {
272
+ width: n.pageWidth + "mm",
273
+ maxWidth: "100%",
274
+ height: "auto",
275
+ boxSizing: "border-box",
276
+ display: "block",
277
+ border: "1px solid #bbb",
278
+ boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
279
+ marginBottom: "16px"
280
+ }), e.appendChild(c);
212
281
  }
213
282
  }
214
283
  export {
215
- B as PAGE_MARGINS,
216
- T as PAGE_SIZES,
217
- A as computeLayout,
218
- v as createPrintClone,
219
- M as insertPageBreakSpacers,
220
- W as normalizeTableAttributes,
221
- j as prepare,
284
+ L as PAGE_MARGINS,
285
+ k as PAGE_SIZES,
286
+ M as computeLayout,
287
+ A as createPrintClone,
288
+ j as insertPageBreakSpacers,
289
+ E as normalizeTableAttributes,
290
+ B as prepare,
291
+ q as previewPageImages,
222
292
  D as renderHTML,
223
293
  F as renderImagePDF,
224
- C as splitOversizedTables,
225
- P as splitOversizedText
294
+ I as renderPageImages,
295
+ R as splitOversizedTables,
296
+ N as splitOversizedText
226
297
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jspdf-utils",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Utility helpers for jsPDF's doc.html() renderer with automatic page breaking, table splitting, and RTL support",
5
5
  "type": "module",
6
6
  "main": "dist/html-to-pdf.js",