jspdf-utils 0.1.2 → 0.1.3

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