jspdf-utils 0.1.3 → 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.
@@ -38,18 +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 and position it off-screen at print width for measurement.
42
- */
43
- declare function createPrintClone(source: HTMLElement, pageWidth?: number): HTMLElement;
44
- /**
45
- * Inline computed styles from `source` onto the matching elements in `clone`.
41
+ * Clone an element into a hidden iframe so that the page's CSS frameworks
42
+ * (Tailwind, Bootstrap, etc.) cannot interfere with PDF rendering.
46
43
  *
47
- * jsPDF's doc.html() has its own CSS engine that can misinterpret styles
48
- * injected by frameworks like Tailwind. By "baking" the browser's computed
49
- * values as inline styles on the clone, we bypass jsPDF's CSS processing
50
- * entirely and get consistent output across all environments.
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.
51
46
  */
52
- declare function inlineComputedStyles(source: HTMLElement, clone: HTMLElement): void;
47
+ declare function createPrintClone(source: HTMLElement, pageWidth?: number): HTMLElement;
53
48
  /**
54
49
  * Convert HTML table attributes (cellpadding, cellspacing, border) to
55
50
  * inline CSS so doc.html()'s renderer picks them up.
@@ -90,4 +85,4 @@ export interface ImagePDFOptions {
90
85
  * screenshot — no selectable or extractable text in the output.
91
86
  */
92
87
  declare function renderImagePDF(source: HTMLElement, opts?: Partial<PageOptions> & ImagePDFOptions): Promise<jsPDF>;
93
- export { PAGE_SIZES, PAGE_MARGINS, computeLayout, createPrintClone, inlineComputedStyles, normalizeTableAttributes, splitOversizedTables, splitOversizedText, insertPageBreakSpacers, prepare, renderHTML, renderImagePDF, };
88
+ export { PAGE_SIZES, PAGE_MARGINS, computeLayout, createPrintClone, normalizeTableAttributes, splitOversizedTables, splitOversizedText, insertPageBreakSpacers, prepare, renderHTML, renderImagePDF, };
@@ -1,5 +1,5 @@
1
- import N from "html2canvas";
2
- const T = {
1
+ import D from "html2canvas";
2
+ const N = {
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
- }, k = {
13
+ }, R = {
14
14
  a0: 40,
15
15
  a1: 35,
16
16
  a2: 30,
@@ -22,251 +22,228 @@ const T = {
22
22
  legal: 25.4,
23
23
  tabloid: 25
24
24
  };
25
- function A(i = {}) {
26
- const o = i.format ?? "a4", [n, t] = T[o], r = i.pageWidth ?? n, e = i.pageHeight ?? t, a = k[o], l = {
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: i.unit ?? "mm",
34
- format: o,
35
- pageWidth: r,
36
- pageHeight: e,
37
- margin: { ...l, ...i.margin }
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 x(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 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 P(i, o = 210) {
45
- const n = i.cloneNode(!0);
46
- return Object.assign(n.style, {
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: "0",
50
- boxSizing: "border-box",
51
- width: o + "mm",
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(n), n;
55
- }
56
- function q(i, o) {
57
- const n = [
58
- "display",
59
- "vertical-align",
60
- "text-align",
61
- "line-height",
62
- "box-sizing",
63
- "padding-top",
64
- "padding-right",
65
- "padding-bottom",
66
- "padding-left",
67
- "border-top-width",
68
- "border-right-width",
69
- "border-bottom-width",
70
- "border-left-width",
71
- "border-top-style",
72
- "border-right-style",
73
- "border-bottom-style",
74
- "border-left-style",
75
- "border-top-color",
76
- "border-right-color",
77
- "border-bottom-color",
78
- "border-left-color",
79
- "border-collapse",
80
- "border-spacing",
81
- "font-family",
82
- "font-size",
83
- "font-weight",
84
- "font-style",
85
- "color",
86
- "background-color",
87
- "direction",
88
- "unicode-bidi",
89
- "table-layout",
90
- "white-space"
91
- ], t = (l, s) => {
92
- const h = getComputedStyle(l);
93
- for (const c of n)
94
- s.style.setProperty(c, h.getPropertyValue(c));
95
- };
96
- t(i, o);
97
- const r = i.querySelectorAll("*"), e = o.querySelectorAll("*"), a = Math.min(r.length, e.length);
98
- for (let l = 0; l < a; l++)
99
- t(r[l], e[l]);
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;
100
77
  }
101
- function v(i) {
102
- for (const o of i.querySelectorAll("table")) {
103
- const n = o.getAttribute("cellpadding");
104
- if (n) {
105
- for (const t of o.querySelectorAll("th, td"))
106
- t.style.padding || (t.style.padding = n + "px");
107
- o.removeAttribute("cellpadding");
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");
108
85
  }
109
86
  }
110
87
  }
111
- function C(i, o) {
112
- for (const n of Array.from(
113
- i.querySelectorAll(":scope > table")
88
+ function E(r, n) {
89
+ for (const i of Array.from(
90
+ r.querySelectorAll(":scope > table")
114
91
  )) {
115
- if (n.offsetHeight <= o) continue;
116
- const t = Array.from(n.rows);
117
- if (t.length === 0) continue;
118
- const r = t[0].querySelector("th") !== null, e = r ? t[0] : null, a = r ? t.slice(1) : t, l = e ? e.offsetHeight : 0, s = o - l - 2, h = [];
119
- let c = [], f = 0;
120
- for (const d of a) {
121
- const g = d.offsetHeight;
122
- f + g > s && c.length > 0 && (h.push(c), c = [], f = 0), c.push(d), f += g;
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;
123
100
  }
124
- c.length > 0 && h.push(c);
125
- for (const d of h) {
126
- const g = n.cloneNode(!1);
127
- e && g.appendChild(e.cloneNode(!0));
128
- for (const m of d) g.appendChild(m.cloneNode(!0));
129
- n.parentNode.insertBefore(g, n);
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);
130
107
  }
131
- n.remove();
108
+ i.remove();
132
109
  }
133
110
  }
134
- function S(i, o) {
135
- for (const n of Array.from(i.querySelectorAll(":scope > *"))) {
136
- const t = n;
137
- if (t.offsetHeight <= o || t.tagName === "TABLE")
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")
138
116
  continue;
139
- const r = t.tagName, e = t.getAttribute("style") || "", a = getComputedStyle(t).width, l = (t.textContent || "").split(/\s+/).filter(Boolean), s = document.createElement(r);
140
- s.setAttribute("style", e), Object.assign(s.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, {
141
119
  position: "absolute",
142
120
  visibility: "hidden",
143
- width: a
144
- }), i.appendChild(s);
145
- const h = [];
146
- let c = 0;
147
- for (; c < l.length; ) {
148
- let f = c + 1, d = l.length;
149
- for (; f < d; ) {
150
- const m = Math.ceil((f + d) / 2);
151
- s.textContent = l.slice(c, m).join(" "), s.offsetHeight <= o ? f = m : d = m - 1;
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;
152
130
  }
153
- const g = document.createElement(r);
154
- g.setAttribute("style", e), g.textContent = l.slice(c, f).join(" "), h.push(g), c = f;
131
+ const m = i.createElement(t);
132
+ m.setAttribute("style", a), m.textContent = l.slice(h, s).join(" "), f.push(m), h = s;
155
133
  }
156
- s.remove();
157
- for (const f of h)
158
- t.parentNode.insertBefore(f, t);
159
- t.remove();
134
+ d.remove();
135
+ for (const s of f)
136
+ o.parentNode.insertBefore(s, o);
137
+ o.remove();
160
138
  }
161
139
  }
162
- function W(i, o) {
163
- const n = Array.from(i.children);
164
- for (const t of n) {
165
- const r = t.offsetTop, e = r + t.offsetHeight, a = (Math.floor(r / o) + 1) * o;
166
- if (e > a && t.offsetHeight <= o) {
167
- const l = document.createElement("div");
168
- l.style.height = a - r + 1 + "px", t.parentNode.insertBefore(l, t);
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);
169
147
  }
170
148
  }
171
149
  }
172
- function B(i, o = {}) {
173
- const n = A(o), t = P(i, n.pageWidth);
174
- q(i, t), v(t);
175
- const r = x(t, n);
176
- return C(t, r.pageContentPx), S(t, r.pageContentPx), W(t, r.pageContentPx), {
177
- clone: t,
178
- layout: r,
179
- options: n,
180
- cleanup: () => t.remove()
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()
181
159
  };
182
160
  }
183
- async function R(i, o, n = {}) {
184
- const { clone: t, layout: r, options: e, cleanup: a } = B(o, n);
161
+ async function F(r, n, i = {}) {
162
+ const { clone: e, layout: o, options: t, cleanup: a } = T(n, i);
185
163
  try {
186
- await new Promise((l) => {
187
- i.html(t, {
188
- callback: () => l(),
189
- width: r.contentWidthMm,
190
- windowWidth: r.renderedWidth,
164
+ await new Promise((c) => {
165
+ r.html(e, {
166
+ callback: () => c(),
167
+ width: o.contentWidthMm,
168
+ windowWidth: o.renderedWidth,
191
169
  margin: [
192
- e.margin.top,
193
- e.margin.right,
194
- e.margin.bottom,
195
- e.margin.left
170
+ t.margin.top,
171
+ t.margin.right,
172
+ t.margin.bottom,
173
+ t.margin.left
196
174
  ]
197
175
  });
198
176
  });
199
177
  } finally {
200
178
  a();
201
179
  }
202
- return i;
180
+ return r;
203
181
  }
204
- async function j(i, o = {}) {
205
- const { imageFormat: n = "JPEG", imageQuality: t = 1, scale: r = 2 } = o, e = A(o), a = P(i, e.pageWidth);
206
- a.style.opacity = "1", a.style.left = "-99999px", v(a);
207
- const l = x(a, e);
208
- C(a, l.pageContentPx), S(a, l.pageContentPx), W(a, l.pageContentPx);
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);
209
187
  try {
210
- const s = await N(a, {
211
- scale: r,
188
+ const l = await D(a, {
189
+ scale: o,
212
190
  backgroundColor: "#ffffff"
213
- }), { jsPDF: h } = await import("jspdf"), c = e.pageWidth - e.margin.left - e.margin.right, f = e.pageHeight - e.margin.top - e.margin.bottom, d = s.width, g = f / c * d, m = Math.ceil(s.height / g), H = e.pageWidth > e.pageHeight ? "l" : "p", w = new h({
214
- orientation: H,
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,
215
193
  unit: "mm",
216
- format: [e.pageWidth, e.pageHeight]
194
+ format: [t.pageWidth, t.pageHeight]
217
195
  });
218
196
  for (let p = 0; p < m; p++) {
219
- const u = Math.min(
197
+ const y = Math.min(
220
198
  g,
221
- s.height - p * g
199
+ l.height - p * g
222
200
  ), b = document.createElement("canvas");
223
- b.width = d, b.height = u;
224
- const y = b.getContext("2d");
225
- if (!y) throw new Error("Could not get canvas context");
226
- y.fillStyle = "#ffffff", y.fillRect(0, 0, d, u), y.drawImage(
227
- s,
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(
205
+ l,
228
206
  0,
229
207
  p * g,
230
- d,
231
- u,
208
+ s,
209
+ y,
232
210
  0,
233
211
  0,
234
- d,
235
- u
212
+ s,
213
+ y
236
214
  );
237
- const M = b.toDataURL(
238
- `image/${n.toLowerCase()}`,
239
- t
215
+ const S = b.toDataURL(
216
+ `image/${i.toLowerCase()}`,
217
+ e
240
218
  );
241
- p > 0 && w.addPage([e.pageWidth, e.pageHeight], H);
242
- const E = u / d * c;
243
- w.addImage(
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,
244
227
  M,
245
- n,
246
- e.margin.left,
247
- e.margin.top,
248
- c,
249
- E,
250
228
  void 0,
251
229
  "FAST"
252
230
  );
253
231
  }
254
- return w;
232
+ return H;
255
233
  } finally {
256
234
  a.remove();
257
235
  }
258
236
  }
259
237
  export {
260
- k as PAGE_MARGINS,
261
- T as PAGE_SIZES,
262
- x as computeLayout,
263
- P as createPrintClone,
264
- q as inlineComputedStyles,
238
+ R as PAGE_MARGINS,
239
+ N as PAGE_SIZES,
240
+ C as computeLayout,
241
+ v as createPrintClone,
265
242
  W as insertPageBreakSpacers,
266
- v as normalizeTableAttributes,
267
- B as prepare,
268
- R as renderHTML,
269
- j as renderImagePDF,
270
- C as splitOversizedTables,
271
- S as splitOversizedText
243
+ A as normalizeTableAttributes,
244
+ T as prepare,
245
+ F as renderHTML,
246
+ B as renderImagePDF,
247
+ E as splitOversizedTables,
248
+ P as splitOversizedText
272
249
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jspdf-utils",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
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",