jspdf-md-renderer 3.3.2 → 3.4.0

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/index.mjs CHANGED
@@ -1,1339 +1,974 @@
1
- import { marked as j } from "marked";
2
- import z from "jspdf-autotable";
3
- var u = /* @__PURE__ */ ((t) => (t.Heading = "heading", t.Paragraph = "paragraph", t.List = "list", t.ListItem = "list_item", t.Blockquote = "blockquote", t.Code = "code", t.CodeSpan = "codespan", t.Table = "table", t.Html = "html", t.Hr = "hr", t.Image = "image", t.Link = "link", t.Strong = "strong", t.Em = "em", t.TableHeader = "table_header", t.TableCell = "table_cell", t.Raw = "raw", t.Text = "text", t))(u || {});
4
- const A = "__jmr_", O = /(!\[[^\]]*\]\()([^)]+)(\))\s*\{([^}]+)\}/g, q = /(\w+)\s*=\s*(\w+)/g, G = ["left", "center", "right"], U = (t) => {
5
- const e = [];
6
- return t.width !== void 0 && e.push(`w=${t.width}`), t.height !== void 0 && e.push(`h=${t.height}`), t.align && e.push(`a=${t.align}`), e.length > 0 ? `#${A}${e.join("&")}` : "";
7
- }, Q = (t) => {
8
- const e = {};
9
- let i;
10
- for (; (i = q.exec(t)) !== null; ) {
11
- const r = i[1].toLowerCase(), c = i[2];
12
- switch (r) {
13
- case "width":
14
- case "w": {
15
- const o = parseInt(c, 10);
16
- !isNaN(o) && o > 0 && (e.width = o);
17
- break;
18
- }
19
- case "height":
20
- case "h": {
21
- const o = parseInt(c, 10);
22
- !isNaN(o) && o > 0 && (e.height = o);
23
- break;
24
- }
25
- case "align": {
26
- const o = c.toLowerCase();
27
- G.includes(
28
- o
29
- ) && (e.align = o);
30
- break;
31
- }
32
- }
33
- }
34
- return e;
35
- }, V = (t) => t.replace(
36
- O,
37
- (e, i, r, c, o) => {
38
- const g = Q(o), a = U(g);
39
- return `${i}${r}${a}${c}`;
40
- }
41
- ), Z = (t) => {
42
- const e = t.indexOf(`#${A}`);
43
- if (e === -1)
44
- return { cleanHref: t, attrs: {} };
45
- const i = t.substring(0, e), r = t.substring(e + 1 + A.length), c = {}, o = r.split("&");
46
- for (const g of o) {
47
- const [a, s] = g.split("=");
48
- switch (a) {
49
- case "w": {
50
- const l = parseInt(s, 10);
51
- !isNaN(l) && l > 0 && (c.width = l);
52
- break;
53
- }
54
- case "h": {
55
- const l = parseInt(s, 10);
56
- !isNaN(l) && l > 0 && (c.height = l);
57
- break;
58
- }
59
- case "a": {
60
- G.includes(
61
- s
62
- ) && (c.align = s);
63
- break;
64
- }
65
- }
66
- }
67
- return { cleanHref: i, attrs: c };
68
- }, K = async (t) => {
69
- const e = V(t), i = await j.lexer(e, {
70
- async: !0,
71
- gfm: !0
72
- });
73
- return w(i);
74
- }, w = (t) => {
75
- const e = [];
76
- return t.forEach((i) => {
77
- try {
78
- const r = M[i.type];
79
- r ? e.push(r(i)) : e.push({
80
- type: u.Raw,
81
- content: i.raw
82
- });
83
- } catch (r) {
84
- console.error("Failed to handle token ==>", i, r);
85
- }
86
- }), e;
87
- }, M = {
88
- [u.Heading]: (t) => ({
89
- type: u.Heading,
90
- depth: t.depth,
91
- content: t.text,
92
- items: t.tokens ? w(t.tokens) : []
93
- }),
94
- [u.Paragraph]: (t) => ({
95
- type: u.Paragraph,
96
- content: t.text,
97
- items: t.tokens ? w(t.tokens) : []
98
- }),
99
- [u.List]: (t) => ({
100
- type: u.List,
101
- ordered: t.ordered,
102
- start: t.start,
103
- items: t.items ? w(t.items) : []
104
- }),
105
- [u.ListItem]: (t) => ({
106
- type: u.ListItem,
107
- content: t.text,
108
- items: t.tokens ? w(t.tokens) : []
109
- }),
110
- [u.Code]: (t) => ({
111
- type: u.Code,
112
- lang: t.lang,
113
- code: t.text
114
- }),
115
- [u.Table]: (t) => ({
116
- type: u.Table,
117
- header: t.header.map((e) => ({
118
- type: u.TableHeader,
119
- content: e.text
120
- })),
121
- rows: t.rows.map(
122
- (e) => e.map((i) => ({
123
- type: u.TableCell,
124
- content: i.text
125
- }))
126
- )
127
- }),
128
- [u.Image]: (t) => {
129
- const { cleanHref: e, attrs: i } = Z(t.href);
130
- return {
131
- type: u.Image,
132
- src: e,
133
- alt: t.text,
134
- width: i.width,
135
- height: i.height,
136
- align: i.align
137
- };
138
- },
139
- [u.Link]: (t) => ({
140
- type: u.Link,
141
- href: t.href,
142
- text: t.text,
143
- items: t.tokens ? w(t.tokens) : []
144
- }),
145
- [u.Strong]: (t) => ({
146
- type: u.Strong,
147
- content: t.text,
148
- items: t.tokens ? w(t.tokens) : []
149
- }),
150
- [u.Em]: (t) => ({
151
- type: u.Em,
152
- content: t.text,
153
- items: t.tokens ? w(t.tokens) : []
154
- }),
155
- [u.Text]: (t) => ({
156
- type: u.Text,
157
- content: t.text,
158
- items: t.tokens ? w(t.tokens) : []
159
- }),
160
- [u.Hr]: (t) => ({
161
- type: u.Hr,
162
- content: t.raw,
163
- items: t.tokens ? w(t.tokens) : []
164
- }),
165
- [u.CodeSpan]: (t) => ({
166
- type: u.CodeSpan,
167
- content: t.text,
168
- items: t.tokens ? w(t.tokens) : []
169
- }),
170
- [u.Blockquote]: (t) => ({
171
- type: u.Blockquote,
172
- content: t.text,
173
- items: t.tokens ? w(t.tokens) : []
174
- })
175
- }, I = class I {
176
- static initialize(e) {
177
- this.options_ = e, this.cursor = { x: e.cursor.x, y: e.cursor.y }, this.lastContentY_ = e.cursor.y;
178
- }
179
- static getCursor() {
180
- return this.cursor;
181
- }
182
- static setCursor(e) {
183
- this.cursor = e;
184
- }
185
- static get options() {
186
- return this.options_;
187
- }
188
- static get isInlineLockActive() {
189
- return this.inlineLock;
190
- }
191
- static activateInlineLock() {
192
- this.inlineLock = !0;
193
- }
194
- static deactivateInlineLock() {
195
- this.inlineLock = !1;
196
- }
197
- /**
198
- * Updates the x pointer of the cursor.
199
- * @param value The value to set or add.
200
- * @param operation 'set' to assign a new value, 'add' to increment the current value.
201
- * @default operation = 'set'
202
- */
203
- static updateX(e, i = "set") {
204
- i === "set" ? this.cursor.x = e : i === "add" && (this.cursor.x += e);
205
- }
206
- /**
207
- * Updates the y pointer of the cursor.
208
- * @param value The value to set or add.
209
- * @param operation 'set' to assign a new value, 'add' to increment the current value.
210
- * @default operation = 'set'
211
- */
212
- static updateY(e, i = "set") {
213
- i === "set" ? this.cursor.y = e : i === "add" && (this.cursor.y += e);
214
- }
215
- /**
216
- * Records a Y position as the bottom of rendered content.
217
- * This is useful for container components (like blockquotes) to know
218
- * where their actual text content ends, ignoring any trailing margins.
219
- * @param specificY Optional Y value to record. Defaults to current cursor Y.
220
- */
221
- static recordContentY(e) {
222
- this.lastContentY_ = e !== void 0 ? e : this.cursor.y;
223
- }
224
- /**
225
- * Gets the last Y position recorded as content bottom.
226
- */
227
- static get lastContentY() {
228
- return this.lastContentY_;
229
- }
230
- // Convenience methods to get individual x and y values
231
- static get X() {
232
- return this.cursor.x;
233
- }
234
- static get Y() {
235
- return this.cursor.y;
236
- }
237
- };
238
- I.cursor = { x: 0, y: 0 }, I.lastContentY_ = 0, I.inlineLock = !1;
239
- let n = I;
240
- const F = (t) => t.getTextDimensions("H").h * n.options.page.defaultLineHeightFactor, H = (t) => t.getTextDimensions("H").w * n.options.page.defaultLineHeightFactor, tt = (t, e, i, r) => {
241
- const c = 6 - (e?.depth ?? 0) > 0 ? 6 - (e?.depth ?? 0) : 1;
242
- if (t.setFontSize(n.options.page.defaultFontSize + c), e?.items && e?.items.length > 0)
243
- for (const o of e?.items ?? [])
244
- r(o, i, !1);
245
- else {
246
- const o = F(t);
247
- t.text(
248
- e?.content ?? "",
249
- n.X + i,
250
- n.Y,
251
- {
252
- align: "left",
253
- maxWidth: n.options.page.maxContentWidth - i,
254
- baseline: "top"
255
- }
256
- ), n.recordContentY(n.Y + o), n.updateY(o, "add");
257
- }
258
- t.setFontSize(n.options.page.defaultFontSize), n.updateX(n.options.page.xpading, "set");
259
- }, Y = (t) => {
260
- typeof n.options.pageBreakHandler == "function" ? n.options.pageBreakHandler(t) : t.addPage(
261
- n.options.page?.format,
262
- n.options.page?.orientation
263
- ), n.updateY(n.options.page.topmargin), n.updateX(n.options.page.xpading);
264
- }, v = 96, k = (t, e = "mm") => {
265
- switch (e) {
266
- case "pt":
267
- return t * 72 / v;
268
- case "in":
269
- return t / v;
270
- case "px":
271
- return t;
272
- default:
273
- return t * 25.4 / v;
274
- }
275
- }, _ = (t) => {
276
- try {
277
- let e = "";
278
- if (t.includes("base64,")) {
279
- const a = t.split("base64,")[1];
280
- typeof window < "u" && typeof window.atob == "function" ? e = decodeURIComponent(escape(window.atob(a))) : typeof Buffer < "u" ? e = Buffer.from(a, "base64").toString("utf-8") : e = decodeURIComponent(escape(atob(a)));
281
- } else
282
- e = decodeURIComponent(t.split(",")[1] || "");
283
- const i = e.match(
284
- /<svg[^>]*\swidth=(?:'|")([0-9.]+)[a-zA-Z]*(?:'|")/i
285
- ), r = e.match(
286
- /<svg[^>]*\sheight=(?:'|")([0-9.]+)[a-zA-Z]*(?:'|")/i
287
- ), c = e.match(
288
- /<svg[^>]*\sviewBox=(?:'|")[^'"]*(?:'|")/i
289
- );
290
- let o = i ? parseFloat(i[1]) : 0, g = r ? parseFloat(r[1]) : 0;
291
- if ((!o || !g) && c) {
292
- const a = c[0].match(
293
- /viewBox=(?:'|")([^'"]+)(?:'|")/i
294
- );
295
- if (a) {
296
- const s = a[1].split(/[ ,]+/).filter(Boolean).map(parseFloat);
297
- s.length >= 4 && (o = o || s[2], g = g || s[3]);
298
- }
299
- }
300
- if (o > 0 && g > 0) return { width: o, height: g };
301
- } catch (e) {
302
- console.warn("Failed to extract SVG dimensions:", e);
303
- }
304
- return null;
305
- }, $ = (t, e, i, r, c = "mm") => {
306
- if (!e.data)
307
- return { finalWidth: 0, finalHeight: 0 };
308
- let o = e.naturalWidth || 0, g = e.naturalHeight || 0;
309
- if (!o || !g)
310
- if (e.data.startsWith("data:image/svg")) {
311
- const p = _(e.data);
312
- p && (o = p.width, g = p.height);
313
- } else
314
- try {
315
- const p = t.getImageProperties(e.data);
316
- o = p.width, g = p.height;
317
- } catch (p) {
318
- console.warn(
319
- "Failed to get image properties for intrinsic sizing:",
320
- p
321
- );
322
- }
323
- const a = g > 0 ? o / g : 1;
324
- let s, l;
325
- if (e.width && e.height ? (s = k(e.width, c), l = k(e.height, c)) : e.width ? (s = k(e.width, c), l = s / a) : e.height ? (l = k(e.height, c), s = l * a) : (s = k(o, c), l = k(g, c)), s > i) {
326
- const p = i / s;
327
- s = i, l = l * p;
328
- }
329
- if (l > r) {
330
- const p = r / l;
331
- l = r, s = s * p;
332
- }
333
- return { finalWidth: s, finalHeight: l };
334
- }, J = async (t) => {
335
- for (const e of t) {
336
- if (e.type === u.Image && e.src)
337
- try {
338
- if (e.src.startsWith("data:"))
339
- e.data = e.src;
340
- else {
341
- const i = await fetch(e.src);
342
- if (!i.ok)
343
- throw new Error(
344
- `Failed to fetch image: ${i.statusText}`
345
- );
346
- const r = await i.blob(), c = await new Promise(
347
- (o, g) => {
348
- const a = new FileReader();
349
- a.onloadend = () => {
350
- typeof a.result == "string" ? o(a.result) : g(
351
- new Error(
352
- "Failed to convert image to base64 string"
353
- )
354
- );
355
- }, a.onerror = g, a.readAsDataURL(r);
356
- }
357
- );
358
- e.data = c;
359
- }
360
- e.data && e.data.startsWith("data:image/svg") && typeof window < "u" && typeof document < "u" && (e.data = await new Promise((i) => {
361
- const r = new Image();
362
- r.onload = () => {
363
- const c = document.createElement("canvas"), o = _(
364
- e.data
365
- ), g = o ? o.width : r.width || 300, a = o ? o.height : r.height || 150;
366
- e.naturalWidth = g, e.naturalHeight = a;
367
- const s = 4;
368
- c.width = g * s, c.height = a * s;
369
- const l = c.getContext("2d");
370
- l ? (l.scale(s, s), l.drawImage(r, 0, 0, g, a), i(c.toDataURL("image/png"))) : i(e.data);
371
- }, r.onerror = () => i(e.data), r.src = e.data;
372
- }));
373
- } catch (i) {
374
- console.warn(
375
- `[jspdf-md-renderer] Warning: Failed to load image at ${e.src}. It will be skipped.`,
376
- i
377
- );
378
- }
379
- e.items && e.items.length > 0 && await J(e.items);
380
- }
381
- };
382
- class B {
383
- // Default codespan styling (can be overridden via RenderStore.options.codespan)
384
- static getCodespanOptions() {
385
- const e = n.options.codespan ?? {};
386
- return {
387
- backgroundColor: e.backgroundColor ?? "#EEEEEE",
388
- padding: e.padding ?? 0.5,
389
- showBackground: e.showBackground !== !1,
390
- fontSizeScale: e.fontSizeScale ?? 0.9
391
- };
392
- }
393
- /**
394
- * Apply font style to the jsPDF document.
395
- */
396
- static applyStyle(e, i) {
397
- const r = e.getFont().fontName, c = e.getFontSize(), o = () => {
398
- const a = n.options.font.bold?.name;
399
- return a && a !== "" ? a : r;
400
- }, g = () => {
401
- const a = n.options.font.regular?.name;
402
- return a && a !== "" ? a : r;
403
- };
404
- switch (i) {
405
- case "bold":
406
- e.setFont(
407
- o(),
408
- n.options.font.bold?.style || "bold"
409
- );
410
- break;
411
- case "italic":
412
- e.setFont(g(), "italic");
413
- break;
414
- case "bolditalic":
415
- e.setFont(o(), "bolditalic");
416
- break;
417
- case "codespan":
418
- e.setFont("courier", "normal"), e.setFontSize(
419
- c * this.getCodespanOptions().fontSizeScale
420
- );
421
- break;
422
- default:
423
- e.setFont(g(), e.getFont().fontStyle);
424
- break;
425
- }
426
- }
427
- /**
428
- * Measure word width with a specific style applied.
429
- * NOTE: jsPDF's getTextWidth() does NOT include charSpace in its calculation,
430
- * so we must manually add it: effectiveWidth = getTextWidth(text) + (text.length * charSpace)
431
- */
432
- static measureWordWidth(e, i, r) {
433
- const c = e.getFont(), o = e.getFontSize();
434
- this.applyStyle(e, r);
435
- const g = e.getTextWidth(i), a = e.getCharSpace?.() ?? 0, s = g + i.length * a;
436
- return e.setFont(c.fontName, c.fontStyle), e.setFontSize(o), s;
437
- }
438
- /**
439
- * Extract style from element type string.
440
- */
441
- static getStyleFromType(e, i) {
442
- switch (e) {
443
- case "strong":
444
- return i === "italic" ? "bolditalic" : "bold";
445
- case "em":
446
- return i === "bold" ? "bolditalic" : "italic";
447
- case "codespan":
448
- return "codespan";
449
- default:
450
- return i || "normal";
451
- }
452
- }
453
- /**
454
- * Flatten ParsedElement tree into an array of StyledWordInfo.
455
- * Handles nested inline elements.
456
- */
457
- static flattenToWords(e, i, r = "normal", c = !1, o) {
458
- const g = [];
459
- for (const a of i) {
460
- const s = this.getStyleFromType(a.type, r), l = a.type === "link" || c, p = a.href || o;
461
- if (a.items && a.items.length > 0) {
462
- const f = this.flattenToWords(
463
- e,
464
- a.items,
465
- s,
466
- l,
467
- p
468
- );
469
- g.push(...f);
470
- } else if (a.type === "image") {
471
- const f = n.options.page.maxContentHeight - n.options.page.topmargin, d = n.options.page.maxContentWidth - n.options.page.indent * 0, h = n.options.page.unit || "mm", { finalWidth: m, finalHeight: x } = $(
472
- e,
473
- a,
474
- d,
475
- f,
476
- h
477
- );
478
- g.push({
479
- text: "",
480
- width: m,
481
- style: s,
482
- isLink: l,
483
- href: p,
484
- linkColor: l ? n.options.link?.linkColor || [0, 0, 255] : void 0,
485
- isImage: !0,
486
- imageElement: a,
487
- imageHeight: x
488
- });
489
- } else {
490
- const f = a.content || a.text || "";
491
- if (!f) continue;
492
- if (s === "codespan") {
493
- const h = f.trim();
494
- h && g.push({
495
- text: h,
496
- width: this.measureWordWidth(
497
- e,
498
- h,
499
- s
500
- ),
501
- style: s,
502
- isLink: l,
503
- href: p,
504
- linkColor: l ? n.options.link?.linkColor || [
505
- 0,
506
- 0,
507
- 255
508
- ] : void 0
509
- });
510
- continue;
511
- }
512
- const d = f.split(/\s+/).filter((h) => h.length > 0);
513
- if (d.length === 0)
514
- continue;
515
- for (let h = 0; h < d.length; h++) {
516
- const m = d[h];
517
- g.push({
518
- text: m,
519
- width: this.measureWordWidth(e, m, s),
520
- style: s,
521
- isLink: l,
522
- href: p,
523
- linkColor: l ? n.options.link?.linkColor || [0, 0, 255] : void 0
524
- });
525
- }
526
- }
527
- }
528
- return g;
529
- }
530
- /**
531
- * Break a flat list of words into lines that fit within maxWidth.
532
- * Correctly tracks totalTextWidth (sum of word widths only) for justification.
533
- */
534
- static breakIntoLines(e, i, r) {
535
- const c = [];
536
- let o = [], g = 0, a = 0, s = F(e) * n.options.page.defaultLineHeightFactor;
537
- const l = e.getTextWidth(" ");
538
- for (let p = 0; p < i.length; p++) {
539
- const f = i[p], d = o.length > 0 ? l + f.width : f.width, h = f.isImage && f.imageHeight ? f.imageHeight : F(e) * n.options.page.defaultLineHeightFactor;
540
- a + d > r && o.length > 0 ? (c.push({
541
- words: o,
542
- totalTextWidth: g,
543
- isLastLine: !1,
544
- lineHeight: s
545
- }), o = [f], g = f.width, a = f.width, s = h) : (o.push(f), g += f.width, a += d, s = Math.max(s, h));
546
- }
547
- return o.length > 0 && c.push({
548
- words: o,
549
- totalTextWidth: g,
550
- isLastLine: !0,
551
- lineHeight: s
552
- }), c;
553
- }
554
- /**
555
- * Render a single word with its style applied.
556
- */
557
- static renderWord(e, i, r, c) {
558
- const o = e.getFont(), g = e.getFontSize(), a = e.getTextColor();
559
- if (this.applyStyle(e, i.style), i.isLink && i.linkColor && e.setTextColor(...i.linkColor), i.isImage && i.imageElement && i.imageElement.data)
560
- try {
561
- let s = "JPEG";
562
- if (i.imageElement.data.startsWith("data:image/png"))
563
- s = "PNG";
564
- else if (i.imageElement.data.startsWith("data:image/webp"))
565
- s = "WEBP";
566
- else if (i.imageElement.data.startsWith("data:image/gif"))
567
- s = "GIF";
568
- else if (i.imageElement.src) {
569
- const p = i.imageElement.src.split("?")[0].split("#")[0].split(".").pop()?.toUpperCase();
570
- p && ["PNG", "JPEG", "JPG", "WEBP", "GIF"].includes(p) && (s = p === "JPG" ? "JPEG" : p);
571
- }
572
- if (i.width > 0 && (i.imageHeight || 0) > 0) {
573
- const l = i.imageHeight || 0, p = c;
574
- e.addImage(
575
- i.imageElement.data,
576
- s,
577
- r,
578
- p,
579
- i.width,
580
- l
581
- );
582
- }
583
- } catch (s) {
584
- console.warn("Failed to render inline image", s);
585
- }
586
- else {
587
- if (i.style === "codespan") {
588
- const s = this.getCodespanOptions();
589
- if (s.showBackground) {
590
- const l = F(e), p = s.padding;
591
- e.setFillColor(s.backgroundColor), e.rect(
592
- r - p,
593
- c - p,
594
- i.width + p * 2,
595
- l + p * 2,
596
- "F"
597
- ), e.setFillColor("#000000");
598
- }
599
- }
600
- e.text(i.text, r, c, { baseline: "top" });
601
- }
602
- if (i.isLink && i.href) {
603
- const s = i.isImage && i.imageHeight ? i.imageHeight : F(e);
604
- e.link(r, c, i.width, s, { url: i.href });
605
- }
606
- e.setFont(o.fontName, o.fontStyle), e.setFontSize(g), e.setTextColor(a);
607
- }
608
- /**
609
- * Render a single line with specified alignment.
610
- */
611
- static renderAlignedLine(e, i, r, c, o, g = "left") {
612
- const { words: a, totalTextWidth: s, isLastLine: l } = i;
613
- if (a.length === 0) return;
614
- const p = e.getTextWidth(" ");
615
- let f = r, d = p;
616
- const h = s + (a.length - 1) * p;
617
- switch (g) {
618
- case "right":
619
- f = r + o - h;
620
- break;
621
- case "center":
622
- f = r + (o - h) / 2;
623
- break;
624
- case "justify":
625
- !l && a.length > 1 && (d = (o - s) / (a.length - 1));
626
- break;
627
- }
628
- let m = f;
629
- const x = F(e) * n.options.page.defaultLineHeightFactor;
630
- for (let b = 0; b < a.length; b++) {
631
- const C = a[b];
632
- let y = c;
633
- const W = C.isImage && C.imageHeight ? C.imageHeight : x;
634
- C.isImage ? y = c : W < i.lineHeight && (y = c + (i.lineHeight - W)), this.renderWord(e, C, m, y), m += C.width, b < a.length - 1 && (m += d);
635
- }
636
- }
637
- /**
638
- * Main entry point: Render a paragraph with mixed inline elements.
639
- * Respects user's textAlignment option from RenderStore.
640
- *
641
- * @param doc jsPDF instance
642
- * @param elements Array of ParsedElement (inline items in a paragraph)
643
- * @param x Starting X coordinate
644
- * @param y Starting Y coordinate
645
- * @param maxWidth Maximum width for text wrapping
646
- * @param alignment Optional alignment override (defaults to RenderStore option)
647
- */
648
- static renderStyledParagraph(e, i, r, c, o, g) {
649
- const a = g ?? n.options.content?.textAlignment ?? "left", s = this.flattenToWords(e, i);
650
- if (s.length === 0) return;
651
- const l = this.breakIntoLines(e, s, o);
652
- let p = c;
653
- for (const d of l)
654
- p + d.lineHeight > n.options.page.maxContentHeight && (Y(e), p = n.Y), this.renderAlignedLine(
655
- e,
656
- d,
657
- r,
658
- p,
659
- o,
660
- a
661
- ), n.recordContentY(p + d.lineHeight), p += d.lineHeight, n.updateY(d.lineHeight, "add");
662
- const f = l[l.length - 1];
663
- if (f) {
664
- const d = f.totalTextWidth + (f.words.length - 1) * e.getTextWidth(" ");
665
- n.updateX(r + d, "set");
666
- }
667
- }
668
- /**
669
- * @deprecated Use renderStyledParagraph instead
670
- */
671
- static renderJustifiedParagraph(e, i, r, c, o) {
672
- this.renderStyledParagraph(e, i, r, c, o);
673
- }
674
- }
675
- class L {
676
- /**
677
- * Renders text with automatic line wrapping and page breaking.
678
- * @param doc jsPDF instance
679
- * @param text Text to render
680
- * @param x X coordinate (if not provided, uses RenderStore.X)
681
- * @param y Y coordinate (if not provided, uses RenderStore.Y)
682
- * @param maxWidth Max width for text wrapping
683
- * @param justify Whether to justify the text
684
- */
685
- static renderText(e, i, r = n.X, c = n.Y, o, g = !1) {
686
- const a = e.splitTextToSize(i, o), s = F(e), l = s * n.options.page.defaultLineHeightFactor;
687
- let p = c;
688
- for (let f = 0; f < a.length; f++) {
689
- const d = a[f];
690
- p + l > n.options.page.maxContentHeight && (Y(e), p = n.Y), g ? f === a.length - 1 ? e.text(d, r, p, { baseline: "top" }) : e.text(d, r, p, {
691
- maxWidth: o,
692
- align: "justify",
693
- baseline: "top"
694
- }) : e.text(d, r, p, { baseline: "top" }), n.recordContentY(p + s), p += l, n.updateY(l, "add");
695
- }
696
- return p;
697
- }
698
- }
699
- const et = (t, e, i, r) => {
700
- n.activateInlineLock(), t.setFontSize(n.options.page.defaultFontSize);
701
- const c = n.options.page.maxContentWidth - i;
702
- if (e?.items && e?.items.length > 0) {
703
- if (e.items.length === 1 && e.items[0].type === "image") {
704
- r(e.items[0], i, !1), n.updateX(n.options.page.xpading), n.deactivateInlineLock();
705
- return;
706
- }
707
- const o = [
708
- "strong",
709
- "em",
710
- "text",
711
- "codespan",
712
- "link",
713
- "image"
714
- ];
715
- if (e.items.some(
716
- (a) => !o.includes(a.type)
717
- )) {
718
- const a = [], s = () => {
719
- a.length > 0 && (B.renderStyledParagraph(
720
- t,
721
- a,
722
- n.X + i,
723
- n.Y,
724
- c
725
- ), a.length = 0);
726
- };
727
- for (const l of e.items)
728
- o.includes(l.type) ? a.push(l) : (s(), r(l, i, !1));
729
- s();
730
- } else
731
- B.renderStyledParagraph(
732
- t,
733
- e.items,
734
- n.X + i,
735
- n.Y,
736
- c
737
- );
738
- } else {
739
- const o = e.content ?? "", g = n.options.content?.textAlignment ?? "left";
740
- o.trim() && L.renderText(
741
- t,
742
- o,
743
- n.X + i,
744
- n.Y,
745
- c,
746
- g === "justify"
747
- );
748
- }
749
- n.updateX(n.options.page.xpading), n.deactivateInlineLock();
750
- }, nt = (t, e, i, r) => {
751
- t.setFontSize(n.options.page.defaultFontSize);
752
- for (const [c, o] of e?.items?.entries() ?? []) {
753
- const g = e.ordered ? (e.start ?? 0) + c : e.start;
754
- r(
755
- o,
756
- i + 1,
757
- !0,
758
- g,
759
- e.ordered
760
- );
761
- }
762
- }, it = (t, e, i, r, c, o) => {
763
- n.Y + F(t) >= n.options.page.maxContentHeight && Y(t);
764
- const g = n.options, a = i * g.page.indent, s = o ? `${c}. ` : "", l = g.page.xpading;
765
- n.updateX(l, "set"), t.setFont(g.font.regular.name, g.font.regular.style), t.text(s, l + a, n.Y, { baseline: "top" });
766
- const p = t.getTextWidth(s), f = l + a + p, d = g.page.maxContentWidth - a - p;
767
- if (e.items && e.items.length > 0) {
768
- const h = [], m = () => {
769
- h.length > 0 && (B.renderStyledParagraph(
770
- t,
771
- h,
772
- f,
773
- n.Y,
774
- d
775
- ), h.length = 0, n.updateX(l, "set"));
776
- };
777
- for (const x of e.items)
778
- x.type === u.List ? (m(), r(
779
- x,
780
- i,
781
- !0,
782
- c,
783
- x.ordered ?? !1
784
- )) : x.type === u.ListItem ? (m(), r(
785
- x,
786
- i,
787
- !0,
788
- c,
789
- o
790
- )) : h.push(x);
791
- m();
792
- } else if (e.content) {
793
- const h = g.content?.textAlignment ?? "left";
794
- L.renderText(
795
- t,
796
- e.content,
797
- f,
798
- n.Y,
799
- d,
800
- h === "justify"
801
- );
802
- }
803
- }, st = (t, e, i, r, c, o, g, a = !0) => {
804
- if (e?.items && e?.items.length > 0)
805
- for (const s of e?.items ?? [])
806
- c(
807
- s,
808
- i,
809
- r,
810
- o,
811
- g,
812
- a
813
- );
814
- else {
815
- const s = n.options, l = i * s.page.indent, p = r ? g ? `${o}. ` : "• " : "", f = e.content || "", d = s.page.xpading;
816
- if (!f && !p) return;
817
- if (!f.trim() && !p) {
818
- const h = (f.match(/\n/g) || []).length;
819
- if (h > 1) {
820
- const m = h - 1, x = t.getTextDimensions("A").h * s.page.defaultLineHeightFactor, b = m * x;
821
- n.Y + b > s.page.maxContentHeight ? Y(t) : (n.updateY(b, "add"), n.recordContentY(n.Y));
822
- }
823
- return;
824
- }
825
- if (n.updateX(d, "set"), r && p) {
826
- const h = t.getTextWidth(p), m = s.page.maxContentWidth - l - h;
827
- t.setFont(s.font.regular.name, s.font.regular.style), t.text(p, d + l, n.Y, {
828
- baseline: "top"
829
- }), L.renderText(
830
- t,
831
- f,
832
- d + l + h,
833
- n.Y,
834
- m,
835
- a
836
- );
837
- } else {
838
- const h = s.page.maxContentWidth - l;
839
- L.renderText(
840
- t,
841
- f,
842
- d + l,
843
- n.Y,
844
- h,
845
- a
846
- );
847
- }
848
- n.updateX(d, "set");
849
- }
850
- }, at = (t) => {
851
- const e = t.internal.pageSize.getWidth();
852
- t.setLineDashPattern([1, 1], 0), t.setLineWidth(0.1), t.line(
853
- n.options.page.xpading,
854
- n.Y,
855
- e - n.options.page.xpading,
856
- n.Y
857
- ), t.setLineWidth(0.1), t.setLineDashPattern([], 0), n.updateY(F(t), "add");
858
- }, ot = (t, e, i) => {
859
- const r = t.getFont(), c = t.getFontSize();
860
- t.setFont("courier", "normal");
861
- const o = n.options.page.defaultFontSize * 0.9;
862
- t.setFontSize(o);
863
- const g = i * n.options.page.indent, a = n.options.page.maxContentWidth - g - 8, s = t.getLineHeightFactor(), l = o / t.internal.scaleFactor * s, f = (e.code ?? "").replace(/[\r\n\s]+$/, "");
864
- if (!f) {
865
- t.setFont(r.fontName, r.fontStyle), t.setFontSize(c);
866
- return;
867
- }
868
- const d = t.splitTextToSize(f, a);
869
- for (; d.length > 0 && d[d.length - 1].trim() === ""; )
870
- d.pop();
871
- if (d.length === 0) {
872
- t.setFont(r.fontName, r.fontStyle), t.setFontSize(c);
873
- return;
874
- }
875
- const h = 4, m = "#EEEEEE", x = "#DDDDDD";
876
- let b = 0;
877
- for (; b < d.length; ) {
878
- const C = n.options.page.maxContentHeight - n.Y, y = d.length - b, W = C - h * 2;
879
- let S = Math.floor(W / l);
880
- if (S <= 0) {
881
- Y(t);
882
- continue;
883
- }
884
- S > y && (S = y);
885
- const T = d.slice(
886
- b,
887
- b + S
888
- ), E = b === 0, X = b + S >= d.length, N = S * l;
889
- if (E && n.updateY(h, "add"), t.setFillColor(m), t.setDrawColor(x), t.roundedRect(
890
- n.X,
891
- n.Y - h,
892
- n.options.page.maxContentWidth,
893
- N + (E ? h : 0) + (X ? h : 0),
894
- 2,
895
- 2,
896
- "FD"
897
- ), E && e.lang) {
898
- const P = t.getFontSize();
899
- t.setFontSize(10), t.setTextColor("#666666"), t.text(
900
- e.lang,
901
- n.X + n.options.page.maxContentWidth - t.getTextWidth(e.lang) - 4,
902
- n.Y,
903
- { baseline: "top" }
904
- ), t.setFontSize(P), t.setTextColor("#000000");
905
- }
906
- let R = n.Y;
907
- for (const P of T)
908
- t.text(P, n.X + 4, R, { baseline: "top" }), R += l;
909
- n.updateY(N, "add"), n.recordContentY(n.Y + (X ? h : 0)), X && n.updateY(h, "add"), b += S, b < d.length && Y(t);
910
- }
911
- t.setFont(r.fontName, r.fontStyle), t.setFontSize(c);
912
- }, rt = (t, e, i) => {
913
- const r = t.getFont().fontName, c = t.getFont().fontStyle, o = t.getFontSize(), g = (s) => {
914
- switch (s) {
915
- case "normal":
916
- return 0;
917
- case "bold":
918
- return 1;
919
- case "italic":
920
- return 1.5;
921
- case "bolditalic":
922
- return 1.5;
923
- case "codespan":
924
- return 0.5;
925
- default:
926
- return 0;
927
- }
928
- }, a = (s, l) => {
929
- l === "bold" ? t.setFont(
930
- n.options.font.bold.name && n.options.font.bold.name !== "" ? n.options.font.bold.name : r,
931
- n.options.font.bold.style || "bold"
932
- ) : l === "italic" ? t.setFont(n.options.font.regular.name, "italic") : l === "bolditalic" ? t.setFont(
933
- n.options.font.bold.name && n.options.font.bold.name !== "" ? n.options.font.bold.name : r,
934
- "bolditalic"
935
- ) : l === "codespan" ? (t.setFont("courier", "normal"), t.setFontSize(o * 0.9)) : t.setFont(
936
- n.options.font.regular.name,
937
- c
938
- );
939
- const p = n.options.page.maxContentWidth - i - n.X, f = t.splitTextToSize(s, p), d = l === "codespan", h = 1, m = "#EEEEEE";
940
- if (n.isInlineLockActive)
941
- for (let x = 0; x < f.length; x++) {
942
- if (d) {
943
- const b = t.getTextWidth(f[x]) + H(t), C = F(t);
944
- t.setFillColor(m), t.roundedRect(
945
- n.X + i - h,
946
- n.Y - h,
947
- b + h * 2,
948
- C + h * 2,
949
- 2,
950
- 2,
951
- "F"
952
- ), t.setFillColor("#000000");
953
- }
954
- t.text(f[x], n.X + i, n.Y, {
955
- baseline: "top",
956
- maxWidth: p
957
- }), n.updateX(
958
- t.getTextDimensions(f[x]).w + (d ? h * 2 : 1),
959
- "add"
960
- ), x < f.length - 1 && (n.updateY(F(t), "add"), n.updateX(
961
- n.options.page.xpading,
962
- "set"
963
- ));
964
- }
965
- else if (f.length > 1) {
966
- const x = f[0], b = f?.slice(1)?.join(" ");
967
- if (d) {
968
- const W = t.getTextWidth(x) + H(t), S = F(t);
969
- t.setFillColor(m), t.roundedRect(
970
- n.X + (i >= 2 ? i + 2 : 0) - h,
971
- n.Y - h,
972
- W + h * 2,
973
- S + h * 2,
974
- 2,
975
- 2,
976
- "F"
977
- ), t.setFillColor("#000000");
978
- }
979
- t.text(
980
- x,
981
- n.X + (i >= 2 ? i + 2 * g(l) : 0),
982
- n.Y,
983
- {
984
- baseline: "top",
985
- maxWidth: p
986
- }
987
- ), n.updateX(n.options.page.xpading + i), n.updateY(F(t), "add");
988
- const C = n.options.page.maxContentWidth - i - n.options.page.xpading;
989
- t.splitTextToSize(
990
- b,
991
- C
992
- ).forEach((W) => {
993
- if (d) {
994
- const S = t.getTextWidth(W) + H(t), T = F(t);
995
- t.setFillColor(m), t.roundedRect(
996
- n.X + H(t) - h,
997
- n.Y - h,
998
- S + h * 2,
999
- T + h * 2,
1000
- 2,
1001
- 2,
1002
- "F"
1003
- ), t.setFillColor("#000000");
1004
- }
1005
- t.text(
1006
- W,
1007
- n.X + H(t),
1008
- n.Y,
1009
- {
1010
- baseline: "top",
1011
- maxWidth: C
1012
- }
1013
- );
1014
- });
1015
- } else {
1016
- if (d) {
1017
- const x = t.getTextWidth(s) + H(t), b = F(t);
1018
- t.setFillColor(m), t.roundedRect(
1019
- n.X + i - h,
1020
- n.Y - h,
1021
- x + h * 2,
1022
- b + h * 2,
1023
- 2,
1024
- 2,
1025
- "F"
1026
- ), t.setFillColor("#000000");
1027
- }
1028
- t.text(s, n.X + i, n.Y, {
1029
- baseline: "top",
1030
- maxWidth: p
1031
- }), n.updateX(
1032
- t.getTextDimensions(s).w + (i >= 2 ? s.split(" ").length + 2 : 2) * g(l) * 0.5 + (d ? h * 2 : 0),
1033
- "add"
1034
- );
1035
- }
1036
- };
1037
- if (e.type === "text" && e.items && e.items.length > 0)
1038
- for (const s of e.items)
1039
- if (s.type === "codespan")
1040
- a(s.content || "", "codespan");
1041
- else if (s.type === "em" || s.type === "strong") {
1042
- const l = s.type === "em" ? "italic" : "bold";
1043
- if (s.items && s.items.length > 0)
1044
- for (const p of s.items)
1045
- p.type === "strong" && l === "italic" || p.type === "em" && l === "bold" ? a(
1046
- p.content || "",
1047
- "bolditalic"
1048
- ) : a(
1049
- p.content || "",
1050
- l
1051
- );
1052
- else
1053
- a(s.content || "", l);
1054
- } else
1055
- a(s.content || "", "normal");
1056
- else e.type === "em" ? a(e.content || "", "italic") : e.type === "strong" ? a(e.content || "", "bold") : e.type === "codespan" ? a(e.content || "", "codespan") : a(e.content || "", "normal");
1057
- t.setFont(r, c), t.setFontSize(o);
1058
- }, lt = (t, e, i) => {
1059
- const r = t.getFont().fontName, c = t.getFont().fontStyle, o = t.getFontSize(), g = t.getTextColor(), a = n.options.link?.linkColor || [0, 0, 255];
1060
- t.setTextColor(...a);
1061
- const s = n.options.page.maxContentWidth - i - n.X, l = e.text || e.content || "", p = e.href || "", f = t.splitTextToSize(l, s);
1062
- if (n.isInlineLockActive)
1063
- for (let d = 0; d < f.length; d++) {
1064
- const h = t.getTextDimensions(f[d]).w, m = F(t) / 2;
1065
- t.link(
1066
- n.X + i,
1067
- n.Y,
1068
- h,
1069
- m,
1070
- { url: p }
1071
- ), t.text(f[d], n.X + i, n.Y, {
1072
- baseline: "top",
1073
- maxWidth: s
1074
- }), n.updateX(h + 1, "add"), n.X + h > n.options.page.maxContentWidth - i && (n.updateY(m, "add"), n.updateX(
1075
- n.options.page.xpading + i,
1076
- "set"
1077
- )), d < f.length - 1 && (n.updateY(m, "add"), n.updateX(
1078
- n.options.page.xpading + i,
1079
- "set"
1080
- ));
1081
- }
1082
- else if (f.length > 1) {
1083
- const d = f[0], h = f?.slice(1)?.join(" "), m = t.getTextDimensions(d).w, x = F(t) / 2;
1084
- t.link(
1085
- n.X + i,
1086
- n.Y,
1087
- m,
1088
- x,
1089
- { url: p }
1090
- ), t.text(d, n.X + i, n.Y, {
1091
- baseline: "top",
1092
- maxWidth: s
1093
- }), n.updateX(n.options.page.xpading + i), n.updateY(x, "add");
1094
- const b = n.options.page.maxContentWidth - i - n.options.page.xpading;
1095
- t.splitTextToSize(h, b).forEach((y) => {
1096
- const W = t.getTextDimensions(y).w;
1097
- t.link(
1098
- n.X + H(t),
1099
- n.Y,
1100
- W,
1101
- x,
1102
- { url: p }
1103
- ), t.text(
1104
- y,
1105
- n.X + H(t),
1106
- n.Y,
1107
- {
1108
- baseline: "top",
1109
- maxWidth: b
1110
- }
1111
- );
1112
- });
1113
- } else {
1114
- const d = t.getTextDimensions(l).w, h = F(t) / 2;
1115
- t.link(
1116
- n.X + i,
1117
- n.Y,
1118
- d,
1119
- h,
1120
- { url: p }
1121
- ), t.text(l, n.X + i, n.Y, {
1122
- baseline: "top",
1123
- maxWidth: s
1124
- }), n.updateX(d + 2, "add");
1125
- }
1126
- t.setFont(r, c), t.setFontSize(o), t.setTextColor(g);
1127
- }, gt = (t, e, i, r) => {
1128
- const c = n.options, o = i + 1, g = n.X + i * c.page.indent, a = n.Y, s = g + c.page.indent / 2, l = a, p = t.internal.getCurrentPageInfo().pageNumber;
1129
- e.items && e.items.length > 0 && e.items.forEach((h) => {
1130
- r(h, o);
1131
- });
1132
- const f = n.Y, d = t.internal.getCurrentPageInfo().pageNumber;
1133
- t.setDrawColor(100), t.setLineWidth(1);
1134
- for (let h = p; h <= d; h++) {
1135
- t.setPage(h);
1136
- const m = h === p, x = h === d, b = m ? l : c.page.topmargin, C = x ? f : c.page.maxContentHeight;
1137
- t.line(s, b, s, C);
1138
- }
1139
- n.recordContentY(), t.setPage(d);
1140
- }, ct = (t) => {
1141
- if (t.data) {
1142
- if (t.data.startsWith("data:image/png")) return "PNG";
1143
- if (t.data.startsWith("data:image/jpeg") || t.data.startsWith("data:image/jpg"))
1144
- return "JPEG";
1145
- if (t.data.startsWith("data:image/webp") || t.data.startsWith("data:image/webp")) return "WEBP";
1146
- if (t.data.startsWith("data:image/gif")) return "GIF";
1147
- }
1148
- if (t.src) {
1149
- const i = t.src.split("?")[0].split("#")[0].split(".").pop()?.toUpperCase();
1150
- if (i && ["PNG", "JPEG", "JPG", "WEBP", "GIF"].includes(i))
1151
- return i === "JPG" ? "JPEG" : i;
1152
- }
1153
- return "JPEG";
1154
- }, pt = (t, e, i) => {
1155
- if (!e.data)
1156
- return;
1157
- const r = n.options, c = r.page.unit || "mm", o = i * r.page.indent, g = r.page.maxContentWidth - o, a = n.X + o;
1158
- let s = n.Y;
1159
- try {
1160
- const l = r.page.maxContentHeight - r.page.topmargin, { finalWidth: p, finalHeight: f } = $(
1161
- t,
1162
- e,
1163
- g,
1164
- l,
1165
- c
1166
- );
1167
- s + f > r.page.maxContentHeight && (Y(t), s = n.Y);
1168
- const d = e.align || r.image?.defaultAlign || "left";
1169
- let h;
1170
- switch (d) {
1171
- case "right":
1172
- h = a + g - p;
1173
- break;
1174
- case "center":
1175
- h = a + (g - p) / 2;
1176
- break;
1177
- default:
1178
- h = a;
1179
- break;
1180
- }
1181
- const m = ct(e);
1182
- p > 0 && f > 0 && t.addImage(
1183
- e.data,
1184
- m,
1185
- h,
1186
- s,
1187
- p,
1188
- f
1189
- ), n.updateY(f, "add"), n.recordContentY();
1190
- } catch (l) {
1191
- console.warn("Failed to render image", l);
1192
- }
1193
- }, ht = () => {
1194
- const t = z;
1195
- if (typeof z == "function")
1196
- return z;
1197
- if (typeof t.default == "function")
1198
- return t.default;
1199
- if (typeof t.autoTable == "function")
1200
- return t.autoTable;
1201
- throw new Error(
1202
- "Could not resolve jspdf-autotable export. Expected a callable export."
1203
- );
1204
- }, ft = (t, e, i) => {
1205
- if (!e.header || !e.rows)
1206
- return;
1207
- const r = n.options, c = r.page.xmargin + i * r.page.indent, o = [e.header.map((s) => s.content || "")], g = e.rows.map(
1208
- (s) => s.map((l) => l.content || "")
1209
- ), a = r.table || {};
1210
- ht()(t, {
1211
- head: o,
1212
- body: g,
1213
- startY: n.Y,
1214
- margin: { left: c, right: r.page.xmargin },
1215
- ...a,
1216
- didDrawPage: (s) => {
1217
- a.didDrawPage && a.didDrawPage(s);
1218
- },
1219
- didDrawCell: (s) => {
1220
- a.didDrawCell && a.didDrawCell(s), n.setCursor({
1221
- x: n.X,
1222
- y: s.cell.y + s.cell.height + 2 * r.page.lineSpace
1223
- });
1224
- }
1225
- });
1226
- }, D = {
1227
- page: {
1228
- indent: 10,
1229
- maxContentWidth: 190,
1230
- maxContentHeight: 277,
1231
- lineSpace: 1.5,
1232
- defaultLineHeightFactor: 1.2,
1233
- defaultFontSize: 12,
1234
- defaultTitleFontSize: 14,
1235
- topmargin: 10,
1236
- xpading: 10,
1237
- xmargin: 10,
1238
- format: "a4",
1239
- orientation: "p"
1240
- },
1241
- font: {
1242
- bold: { name: "helvetica", style: "bold" },
1243
- regular: { name: "helvetica", style: "normal" },
1244
- light: { name: "helvetica", style: "light" }
1245
- },
1246
- image: {
1247
- defaultAlign: "left"
1248
- }
1249
- }, dt = (t) => {
1250
- if (!t)
1251
- throw new Error("RenderOption is required");
1252
- const e = { ...D.page, ...t.page }, i = { ...D.font, ...t.font }, r = { ...D.image, ...t.image };
1253
- return e.maxContentWidth || (e.maxContentWidth = 190), e.maxContentHeight || (e.maxContentHeight = 277), {
1254
- ...t,
1255
- page: e,
1256
- font: i,
1257
- image: r
1258
- };
1259
- }, xt = async (t, e, i) => {
1260
- const r = dt(i);
1261
- n.initialize(r);
1262
- const c = await K(e);
1263
- await J(c);
1264
- const o = (g, a = 0, s = !1, l = 0, p = !1) => {
1265
- const f = a * r.page.indent;
1266
- switch (g.type) {
1267
- case u.Heading:
1268
- tt(t, g, f, o);
1269
- break;
1270
- case u.Paragraph:
1271
- et(t, g, f, o);
1272
- break;
1273
- case u.List:
1274
- nt(t, g, a, o);
1275
- break;
1276
- case u.ListItem:
1277
- it(
1278
- t,
1279
- g,
1280
- a,
1281
- o,
1282
- l,
1283
- p
1284
- );
1285
- break;
1286
- case u.Hr:
1287
- at(t);
1288
- break;
1289
- case u.Code:
1290
- ot(t, g, a);
1291
- break;
1292
- case u.Strong:
1293
- case u.Em:
1294
- case u.CodeSpan:
1295
- rt(t, g, f);
1296
- break;
1297
- case u.Link:
1298
- lt(t, g, f);
1299
- break;
1300
- case u.Blockquote:
1301
- gt(t, g, a, o);
1302
- break;
1303
- case u.Image:
1304
- pt(t, g, a);
1305
- break;
1306
- case u.Table:
1307
- ft(t, g, a);
1308
- break;
1309
- case u.Raw:
1310
- case u.Text:
1311
- st(
1312
- t,
1313
- g,
1314
- a,
1315
- s,
1316
- o,
1317
- l,
1318
- p,
1319
- r.content?.textAlignment === "justify"
1320
- );
1321
- break;
1322
- default:
1323
- console.warn(
1324
- `Warning: Unsupported element type encountered: ${g.type}.
1
+ import { marked as e } from "marked";
2
+ import t from "jspdf-autotable";
3
+ //#region src/enums/mdTokenType.ts
4
+ var n = /* @__PURE__ */ function(e) {
5
+ return e.Heading = "heading", e.Paragraph = "paragraph", e.List = "list", e.ListItem = "list_item", e.Blockquote = "blockquote", e.Code = "code", e.CodeSpan = "codespan", e.Table = "table", e.Html = "html", e.Hr = "hr", e.Image = "image", e.Link = "link", e.Strong = "strong", e.Em = "em", e.TableHeader = "table_header", e.TableCell = "table_cell", e.Raw = "raw", e.Text = "text", e.Br = "br", e;
6
+ }({}), r = "__jmr_", i = /(!\[[^\]]*\]\()([^)]+)(\))\s*\{([^}]+)\}/g, a = /(\w+)\s*=\s*(\w+)/g, o = [
7
+ "left",
8
+ "center",
9
+ "right"
10
+ ], s = (e) => {
11
+ let t = [];
12
+ return e.width !== void 0 && t.push(`w=${e.width}`), e.height !== void 0 && t.push(`h=${e.height}`), e.align && t.push(`a=${e.align}`), t.length > 0 ? `#${r}${t.join("&")}` : "";
13
+ }, c = (e) => {
14
+ let t = {}, n;
15
+ for (; (n = a.exec(e)) !== null;) {
16
+ let e = n[1].toLowerCase(), r = n[2];
17
+ switch (e) {
18
+ case "width":
19
+ case "w": {
20
+ let e = parseInt(r, 10);
21
+ !isNaN(e) && e > 0 && (t.width = e);
22
+ break;
23
+ }
24
+ case "height":
25
+ case "h": {
26
+ let e = parseInt(r, 10);
27
+ !isNaN(e) && e > 0 && (t.height = e);
28
+ break;
29
+ }
30
+ case "align": {
31
+ let e = r.toLowerCase();
32
+ o.includes(e) && (t.align = e);
33
+ break;
34
+ }
35
+ }
36
+ }
37
+ return t;
38
+ }, l = (e) => e.replace(i, (e, t, n, r, i) => `${t}${n}${s(c(i))}${r}`), u = (e) => {
39
+ let t = e.indexOf(`#${r}`);
40
+ if (t === -1) return {
41
+ cleanHref: e,
42
+ attrs: {}
43
+ };
44
+ let n = e.substring(0, t), i = e.substring(t + 1 + 6), a = {}, s = i.split("&");
45
+ for (let e of s) {
46
+ let [t, n] = e.split("=");
47
+ switch (t) {
48
+ case "w": {
49
+ let e = parseInt(n, 10);
50
+ !isNaN(e) && e > 0 && (a.width = e);
51
+ break;
52
+ }
53
+ case "h": {
54
+ let e = parseInt(n, 10);
55
+ !isNaN(e) && e > 0 && (a.height = e);
56
+ break;
57
+ }
58
+ case "a":
59
+ o.includes(n) && (a.align = n);
60
+ break;
61
+ }
62
+ }
63
+ return {
64
+ cleanHref: n,
65
+ attrs: a
66
+ };
67
+ }, d = async (t) => {
68
+ let n = l(t);
69
+ return f(await e.lexer(n, {
70
+ async: !0,
71
+ gfm: !0
72
+ }));
73
+ }, f = (e) => {
74
+ let t = [];
75
+ return e.forEach((e) => {
76
+ try {
77
+ let r = p[e.type];
78
+ r ? t.push(r(e)) : t.push({
79
+ type: n.Raw,
80
+ content: e.raw
81
+ });
82
+ } catch (t) {
83
+ console.error("Failed to handle token ==>", e, t);
84
+ }
85
+ }), t;
86
+ }, p = {
87
+ [n.Heading]: (e) => ({
88
+ type: n.Heading,
89
+ depth: e.depth,
90
+ content: e.text,
91
+ items: e.tokens ? f(e.tokens) : []
92
+ }),
93
+ [n.Paragraph]: (e) => ({
94
+ type: n.Paragraph,
95
+ content: e.text,
96
+ items: e.tokens ? f(e.tokens) : []
97
+ }),
98
+ [n.List]: (e) => ({
99
+ type: n.List,
100
+ ordered: e.ordered,
101
+ start: e.start,
102
+ items: e.items ? f(e.items) : []
103
+ }),
104
+ [n.ListItem]: (e) => ({
105
+ type: n.ListItem,
106
+ content: e.text,
107
+ items: e.tokens ? f(e.tokens) : []
108
+ }),
109
+ [n.Code]: (e) => ({
110
+ type: n.Code,
111
+ lang: e.lang,
112
+ code: e.text
113
+ }),
114
+ [n.Table]: (e) => ({
115
+ type: n.Table,
116
+ header: e.header.map((e) => ({
117
+ type: n.TableHeader,
118
+ content: e.text
119
+ })),
120
+ rows: e.rows.map((e) => e.map((e) => ({
121
+ type: n.TableCell,
122
+ content: e.text
123
+ })))
124
+ }),
125
+ [n.Image]: (e) => {
126
+ let { cleanHref: t, attrs: r } = u(e.href);
127
+ return {
128
+ type: n.Image,
129
+ src: t,
130
+ alt: e.text,
131
+ width: r.width,
132
+ height: r.height,
133
+ align: r.align
134
+ };
135
+ },
136
+ [n.Link]: (e) => ({
137
+ type: n.Link,
138
+ href: e.href,
139
+ text: e.text,
140
+ items: e.tokens ? f(e.tokens) : []
141
+ }),
142
+ [n.Strong]: (e) => ({
143
+ type: n.Strong,
144
+ content: e.text,
145
+ items: e.tokens ? f(e.tokens) : []
146
+ }),
147
+ [n.Em]: (e) => ({
148
+ type: n.Em,
149
+ content: e.text,
150
+ items: e.tokens ? f(e.tokens) : []
151
+ }),
152
+ [n.Text]: (e) => ({
153
+ type: n.Text,
154
+ content: e.text,
155
+ items: e.tokens ? f(e.tokens) : []
156
+ }),
157
+ [n.Hr]: (e) => ({
158
+ type: n.Hr,
159
+ content: e.raw,
160
+ items: e.tokens ? f(e.tokens) : []
161
+ }),
162
+ [n.CodeSpan]: (e) => ({
163
+ type: n.CodeSpan,
164
+ content: e.text,
165
+ items: e.tokens ? f(e.tokens) : []
166
+ }),
167
+ [n.Blockquote]: (e) => ({
168
+ type: n.Blockquote,
169
+ content: e.text,
170
+ items: e.tokens ? f(e.tokens) : []
171
+ }),
172
+ [n.Html]: (e) => {
173
+ let t = String(e.raw ?? e.text ?? "").trim();
174
+ return /^<br\s*\/?>$/i.test(t) ? {
175
+ type: n.Br,
176
+ content: "\n"
177
+ } : {
178
+ type: n.Raw,
179
+ content: e.raw ?? e.text ?? ""
180
+ };
181
+ },
182
+ [n.Br]: () => ({
183
+ type: n.Br,
184
+ content: "\n"
185
+ })
186
+ }, m = (e) => e.getTextDimensions("H").h, h = (e) => e.getTextDimensions("H").w, g = (e, t, n, r, i) => {
187
+ let a = 6 - (t?.depth ?? 0) > 0 ? 6 - (t?.depth ?? 0) : 1;
188
+ if (e.setFontSize(r.options.page.defaultFontSize + a), t?.items && t?.items.length > 0) for (let e of t?.items ?? []) i(e, n, r, !1);
189
+ else {
190
+ let i = m(e);
191
+ e.text(t?.content ?? "", r.X + n, r.Y, {
192
+ align: "left",
193
+ maxWidth: r.options.page.maxContentWidth - n,
194
+ baseline: "top"
195
+ }), r.recordContentY(r.Y + i), r.updateY(m(e), "add");
196
+ }
197
+ e.setFontSize(r.options.page.defaultFontSize), r.updateX(r.options.page.xpading, "set");
198
+ }, _ = (e, t) => {
199
+ typeof t.options.pageBreakHandler == "function" ? t.options.pageBreakHandler(e) : e.addPage(t.options.page?.format, t.options.page?.orientation), t.updateY(t.options.page.topmargin), t.updateX(t.options.page.xpading);
200
+ }, v = 96, y = (e, t = "mm") => {
201
+ switch (t) {
202
+ case "pt": return e * 72 / v;
203
+ case "in": return e / v;
204
+ case "px": return e;
205
+ default: return e * 25.4 / v;
206
+ }
207
+ }, b = (e) => {
208
+ try {
209
+ let t = "";
210
+ if (e.includes("base64,")) {
211
+ let n = e.split("base64,")[1];
212
+ t = typeof window < "u" && typeof window.atob == "function" ? decodeURIComponent(escape(window.atob(n))) : typeof Buffer < "u" ? Buffer.from(n, "base64").toString("utf-8") : decodeURIComponent(escape(atob(n)));
213
+ } else t = decodeURIComponent(e.split(",")[1] || "");
214
+ let n = t.match(/<svg[^>]*\swidth=(?:'|")([0-9.]+)[a-zA-Z]*(?:'|")/i), r = t.match(/<svg[^>]*\sheight=(?:'|")([0-9.]+)[a-zA-Z]*(?:'|")/i), i = t.match(/<svg[^>]*\sviewBox=(?:'|")[^'"]*(?:'|")/i), a = n ? parseFloat(n[1]) : 0, o = r ? parseFloat(r[1]) : 0;
215
+ if ((!a || !o) && i) {
216
+ let e = i[0].match(/viewBox=(?:'|")([^'"]+)(?:'|")/i);
217
+ if (e) {
218
+ let t = e[1].split(/[ ,]+/).filter(Boolean).map(parseFloat);
219
+ t.length >= 4 && (a ||= t[2], o ||= t[3]);
220
+ }
221
+ }
222
+ if (a > 0 && o > 0) return {
223
+ width: a,
224
+ height: o
225
+ };
226
+ } catch (e) {
227
+ console.warn("Failed to extract SVG dimensions:", e);
228
+ }
229
+ return null;
230
+ }, x = (e, t, n, r, i = "mm") => {
231
+ if (!t.data) return {
232
+ finalWidth: 0,
233
+ finalHeight: 0
234
+ };
235
+ let a = t.naturalWidth || 0, o = t.naturalHeight || 0;
236
+ if (!a || !o) if (t.data.startsWith("data:image/svg")) {
237
+ let e = b(t.data);
238
+ e && (a = e.width, o = e.height);
239
+ } else try {
240
+ let n = e.getImageProperties(t.data);
241
+ a = n.width, o = n.height;
242
+ } catch (e) {
243
+ console.warn("Failed to get image properties for intrinsic sizing:", e);
244
+ }
245
+ let s = o > 0 ? a / o : 1, c, l;
246
+ if (t.width && t.height ? (c = y(t.width, i), l = y(t.height, i)) : t.width ? (c = y(t.width, i), l = c / s) : t.height ? (l = y(t.height, i), c = l * s) : (c = y(a, i), l = y(o, i)), c > n) {
247
+ let e = n / c;
248
+ c = n, l *= e;
249
+ }
250
+ if (l > r) {
251
+ let e = r / l;
252
+ l = r, c *= e;
253
+ }
254
+ return {
255
+ finalWidth: c,
256
+ finalHeight: l
257
+ };
258
+ }, S = async (e) => {
259
+ for (let t of e) {
260
+ if (t.type === n.Image && t.src) try {
261
+ if (t.src.startsWith("data:")) t.data = t.src;
262
+ else {
263
+ let e = await fetch(t.src);
264
+ if (!e.ok) throw Error(`Failed to fetch image: ${e.statusText}`);
265
+ let n = await e.blob();
266
+ t.data = await new Promise((e, t) => {
267
+ let r = new FileReader();
268
+ r.onloadend = () => {
269
+ typeof r.result == "string" ? e(r.result) : t(/* @__PURE__ */ Error("Failed to convert image to base64 string"));
270
+ }, r.onerror = t, r.readAsDataURL(n);
271
+ });
272
+ }
273
+ t.data && t.data.startsWith("data:image/svg") && typeof window < "u" && typeof document < "u" && (t.data = await new Promise((e) => {
274
+ let n = new Image();
275
+ n.onload = () => {
276
+ let r = document.createElement("canvas"), i = b(t.data), a = i ? i.width : n.width || 300, o = i ? i.height : n.height || 150;
277
+ t.naturalWidth = a, t.naturalHeight = o, r.width = a * 4, r.height = o * 4;
278
+ let s = r.getContext("2d");
279
+ s ? (s.scale(4, 4), s.drawImage(n, 0, 0, a, o), e(r.toDataURL("image/png"))) : e(t.data);
280
+ }, n.onerror = () => e(t.data), n.src = t.data;
281
+ }));
282
+ } catch (e) {
283
+ console.warn(`[jspdf-md-renderer] Warning: Failed to load image at ${t.src}. It will be skipped.`, e);
284
+ }
285
+ t.items && t.items.length > 0 && await S(t.items);
286
+ }
287
+ }, C = class {
288
+ static getCodespanOptions(e) {
289
+ let t = e.options.codespan ?? {};
290
+ return {
291
+ backgroundColor: t.backgroundColor ?? "#EEEEEE",
292
+ padding: t.padding ?? .5,
293
+ showBackground: t.showBackground !== !1,
294
+ fontSizeScale: t.fontSizeScale ?? .9
295
+ };
296
+ }
297
+ static applyStyle(e, t, n) {
298
+ let r = e.getFont().fontName, i = e.getFontSize(), a = () => {
299
+ let e = n.options.font.bold?.name;
300
+ return e && e !== "" ? e : r;
301
+ }, o = () => {
302
+ let e = n.options.font.regular?.name;
303
+ return e && e !== "" ? e : r;
304
+ };
305
+ switch (t) {
306
+ case "bold":
307
+ e.setFont(a(), n.options.font.bold?.style || "bold");
308
+ break;
309
+ case "italic":
310
+ e.setFont(o(), "italic");
311
+ break;
312
+ case "bolditalic":
313
+ e.setFont(a(), "bolditalic");
314
+ break;
315
+ case "codespan":
316
+ e.setFont("courier", "normal"), e.setFontSize(i * this.getCodespanOptions(n).fontSizeScale);
317
+ break;
318
+ default:
319
+ e.setFont(o(), e.getFont().fontStyle);
320
+ break;
321
+ }
322
+ }
323
+ static measureWordWidth(e, t, n, r) {
324
+ let i = e.getFont(), a = e.getFontSize();
325
+ this.applyStyle(e, n, r);
326
+ let o = e.getTextWidth(t), s = e.getCharSpace?.() ?? 0, c = o + t.length * s;
327
+ return e.setFont(i.fontName, i.fontStyle), e.setFontSize(a), c;
328
+ }
329
+ static getStyleFromType(e, t) {
330
+ switch (e) {
331
+ case "strong": return t === "italic" ? "bolditalic" : "bold";
332
+ case "em": return t === "bold" ? "bolditalic" : "italic";
333
+ case "codespan": return "codespan";
334
+ default: return t || "normal";
335
+ }
336
+ }
337
+ static flattenToWords(e, t, n, r = "normal", i = !1, a) {
338
+ let o = [];
339
+ for (let s of t) {
340
+ let t = this.getStyleFromType(s.type, r), c = s.type === "link" || i, l = s.href || a;
341
+ if (s.items && s.items.length > 0) {
342
+ let r = this.flattenToWords(e, s.items, n, t, c, l);
343
+ o.push(...r);
344
+ } else if (s.type === "image") {
345
+ let r = n.options.page.maxContentHeight - n.options.page.topmargin, { finalWidth: i, finalHeight: a } = x(e, s, n.options.page.maxContentWidth - n.options.page.indent * 0, r, n.options.page.unit || "mm");
346
+ o.push({
347
+ text: "",
348
+ width: i,
349
+ style: t,
350
+ isLink: c,
351
+ href: l,
352
+ linkColor: c ? n.options.link?.linkColor || [
353
+ 0,
354
+ 0,
355
+ 255
356
+ ] : void 0,
357
+ isImage: !0,
358
+ imageElement: s,
359
+ imageHeight: a
360
+ });
361
+ } else if (s.type === "br") o.push({
362
+ text: "",
363
+ width: 0,
364
+ style: t,
365
+ isBr: !0
366
+ });
367
+ else {
368
+ let r = s.content || s.text || "";
369
+ if (!r) continue;
370
+ if (/^\s/.test(r) && o.length > 0 && (o[o.length - 1].hasTrailingSpace = !0), t === "codespan") {
371
+ let i = r.trim();
372
+ i && o.push({
373
+ text: i,
374
+ width: this.measureWordWidth(e, i, t, n),
375
+ style: t,
376
+ isLink: c,
377
+ href: l,
378
+ linkColor: c ? n.options.link?.linkColor || [
379
+ 0,
380
+ 0,
381
+ 255
382
+ ] : void 0,
383
+ hasTrailingSpace: /\s$/.test(r)
384
+ });
385
+ continue;
386
+ }
387
+ let i = r.trim().split(/\s+/).filter((e) => e.length > 0);
388
+ for (let a = 0; a < i.length; a++) {
389
+ let s = a !== i.length - 1 || /\s$/.test(r);
390
+ o.push({
391
+ text: i[a],
392
+ width: this.measureWordWidth(e, i[a], t, n),
393
+ style: t,
394
+ isLink: c,
395
+ href: l,
396
+ linkColor: c ? n.options.link?.linkColor || [
397
+ 0,
398
+ 0,
399
+ 255
400
+ ] : void 0,
401
+ hasTrailingSpace: s
402
+ });
403
+ }
404
+ }
405
+ }
406
+ return o;
407
+ }
408
+ static breakIntoLines(e, t, n, r) {
409
+ let i = [], a = [], o = 0, s = 0, c = m(e) * r.options.page.defaultLineHeightFactor, l = e.getTextWidth(" ");
410
+ for (let u = 0; u < t.length; u++) {
411
+ let d = t[u], f = a[a.length - 1]?.hasTrailingSpace ? l + d.width : d.width, p = d.isImage && d.imageHeight ? d.imageHeight : m(e) * r.options.page.defaultLineHeightFactor;
412
+ if (d.isBr) {
413
+ i.push({
414
+ words: a,
415
+ totalTextWidth: o,
416
+ isLastLine: !0,
417
+ lineHeight: c
418
+ }), a = [], o = 0, s = 0, c = m(e) * r.options.page.defaultLineHeightFactor;
419
+ continue;
420
+ }
421
+ s + f > n && a.length > 0 ? (i.push({
422
+ words: a,
423
+ totalTextWidth: o,
424
+ isLastLine: !1,
425
+ lineHeight: c
426
+ }), a = [d], o = d.width, s = d.width, c = p) : (a.push(d), o += d.width, s += f, c = Math.max(c, p));
427
+ }
428
+ return a.length > 0 && i.push({
429
+ words: a,
430
+ totalTextWidth: o,
431
+ isLastLine: !0,
432
+ lineHeight: c
433
+ }), i;
434
+ }
435
+ static renderWord(e, t, n, r, i) {
436
+ let a = e.getFont(), o = e.getFontSize(), s = e.getTextColor();
437
+ if (this.applyStyle(e, t.style, i), t.isLink && t.linkColor && e.setTextColor(...t.linkColor), t.isImage && t.imageElement && t.imageElement.data) try {
438
+ let i = "JPEG";
439
+ if (t.imageElement.data.startsWith("data:image/png")) i = "PNG";
440
+ else if (t.imageElement.data.startsWith("data:image/webp")) i = "WEBP";
441
+ else if (t.imageElement.data.startsWith("data:image/gif")) i = "GIF";
442
+ else if (t.imageElement.src) {
443
+ let e = t.imageElement.src.split("?")[0].split("#")[0].split(".").pop()?.toUpperCase();
444
+ e && [
445
+ "PNG",
446
+ "JPEG",
447
+ "JPG",
448
+ "WEBP",
449
+ "GIF"
450
+ ].includes(e) && (i = e === "JPG" ? "JPEG" : e);
451
+ }
452
+ if (t.width > 0 && (t.imageHeight || 0) > 0) {
453
+ let a = t.imageHeight || 0, o = r;
454
+ e.addImage(t.imageElement.data, i, n, o, t.width, a);
455
+ }
456
+ } catch (e) {
457
+ console.warn("Failed to render inline image", e);
458
+ }
459
+ else {
460
+ if (t.style === "codespan") {
461
+ let a = this.getCodespanOptions(i);
462
+ if (a.showBackground) {
463
+ let i = m(e), o = a.padding;
464
+ e.setFillColor(a.backgroundColor), e.rect(n - o, r - o, t.width + o * 2, i + o * 2, "F"), e.setFillColor("#000000");
465
+ }
466
+ }
467
+ e.text(t.text, n, r, { baseline: "top" });
468
+ }
469
+ if (t.isLink && t.href) {
470
+ let i = t.isImage && t.imageHeight ? t.imageHeight : m(e);
471
+ e.link(n, r, t.width, i, { url: t.href });
472
+ }
473
+ e.setFont(a.fontName, a.fontStyle), e.setFontSize(o), e.setTextColor(s);
474
+ }
475
+ static renderAlignedLine(e, t, n, r, i, a, o = "left") {
476
+ let { words: s, totalTextWidth: c, isLastLine: l } = t;
477
+ if (s.length === 0) return;
478
+ let u = e.getTextWidth(" "), d = n, f = u, p = c, h = 0;
479
+ for (let e = 0; e < s.length - 1; e++) s[e].hasTrailingSpace && (p += u, h++);
480
+ switch (o) {
481
+ case "right":
482
+ d = n + i - p;
483
+ break;
484
+ case "center":
485
+ d = n + (i - p) / 2;
486
+ break;
487
+ case "justify":
488
+ !l && h > 0 && (f = (i - c) / h);
489
+ break;
490
+ default: break;
491
+ }
492
+ let g = d, _ = m(e) * a.options.page.defaultLineHeightFactor;
493
+ for (let n = 0; n < s.length; n++) {
494
+ let i = s[n], o = r, c = i.isImage && i.imageHeight ? i.imageHeight : _;
495
+ i.isImage ? o = r : c < t.lineHeight && (o = r + (t.lineHeight - c)), this.renderWord(e, i, g, o, a), g += i.width, n < s.length - 1 && i.hasTrailingSpace && (g += f);
496
+ }
497
+ }
498
+ static renderStyledParagraph(e, t, n, r, i, a, o) {
499
+ let s = o ?? a.options.content?.textAlignment ?? "left", c = this.flattenToWords(e, t, a);
500
+ if (c.length === 0) return;
501
+ let l = this.breakIntoLines(e, c, i, a), u = r;
502
+ for (let t of l) u + t.lineHeight > a.options.page.maxContentHeight && (_(e, a), u = a.Y), this.renderAlignedLine(e, t, n, u, i, a, s), a.recordContentY(u + t.lineHeight), u += t.lineHeight, a.updateY(t.lineHeight, "add");
503
+ let d = l[l.length - 1];
504
+ if (d) {
505
+ let t = 0;
506
+ for (let e = 0; e < d.words.length - 1; e++) d.words[e].hasTrailingSpace && t++;
507
+ let r = d.totalTextWidth + t * e.getTextWidth(" ");
508
+ a.updateX(n + r, "set");
509
+ }
510
+ }
511
+ static renderJustifiedParagraph(e, t, n, r, i, a) {
512
+ this.renderStyledParagraph(e, t, n, r, i, a);
513
+ }
514
+ }, w = class {
515
+ static renderText(e, t, n, r = n.X, i = n.Y, a, o = !1) {
516
+ let s = e.splitTextToSize(t, a), c = m(e), l = c * n.options.page.defaultLineHeightFactor, u = i;
517
+ for (let t = 0; t < s.length; t++) {
518
+ let i = s[t];
519
+ u + l > n.options.page.maxContentHeight && (_(e, n), u = n.Y), o ? t === s.length - 1 ? e.text(i, r, u, { baseline: "top" }) : e.text(i, r, u, {
520
+ maxWidth: a,
521
+ align: "justify",
522
+ baseline: "top"
523
+ }) : e.text(i, r, u, { baseline: "top" }), n.recordContentY(u + c), u += l, n.updateY(l, "add");
524
+ }
525
+ return u;
526
+ }
527
+ }, T = (e, t, r, i, a) => {
528
+ i.activateInlineLock(), e.setFontSize(i.options.page.defaultFontSize);
529
+ let o = i.options.page.maxContentWidth - r;
530
+ if (t?.items && t?.items.length > 0) {
531
+ if (t.items.length === 1 && t.items[0].type === "image") {
532
+ a(t.items[0], r, i, !1), i.updateX(i.options.page.xpading), i.deactivateInlineLock();
533
+ return;
534
+ }
535
+ let s = [
536
+ n.Strong,
537
+ n.Em,
538
+ n.Text,
539
+ n.CodeSpan,
540
+ n.Link,
541
+ n.Image,
542
+ n.Br
543
+ ];
544
+ if (t.items.some((e) => !s.includes(e.type))) {
545
+ let n = [], c = () => {
546
+ n.length > 0 && (C.renderStyledParagraph(e, n, i.X + r, i.Y, o, i), n.length = 0);
547
+ };
548
+ for (let e of t.items) s.includes(e.type) ? n.push(e) : (c(), a(e, r, i, !1));
549
+ c();
550
+ } else C.renderStyledParagraph(e, t.items, i.X + r, i.Y, o, i);
551
+ } else {
552
+ let n = t.content ?? "", a = i.options.content?.textAlignment ?? "left";
553
+ n.trim() && w.renderText(e, n, i, i.X + r, i.Y, o, a === "justify");
554
+ }
555
+ i.updateX(i.options.page.xpading), i.deactivateInlineLock();
556
+ }, E = (e, t, n, r, i) => {
557
+ e.setFontSize(r.options.page.defaultFontSize);
558
+ for (let [e, a] of t?.items?.entries() ?? []) {
559
+ let o = t.ordered ? (t.start ?? 0) + e : t.start;
560
+ i(a, n + 1, r, !0, o, t.ordered);
561
+ }
562
+ }, D = (e, t, r, i, a, o, s) => {
563
+ i.Y + m(e) >= i.options.page.maxContentHeight && _(e, i);
564
+ let c = i.options, l = r * c.page.indent, u = s ? `${o}. ` : "• ", d = c.page.xpading;
565
+ i.updateX(d, "set"), e.setFont(c.font.regular.name, c.font.regular.style), e.text(u, d + l, i.Y, { baseline: "top" });
566
+ let f = e.getTextWidth(u), p = d + l + f, h = c.page.maxContentWidth - l - f;
567
+ if (t.items && t.items.length > 0) {
568
+ let c = [], l = () => {
569
+ c.length > 0 && (C.renderStyledParagraph(e, c, p, i.Y, h, i), c.length = 0, i.updateX(d, "set"));
570
+ };
571
+ for (let e of t.items) e.type === n.List ? (l(), a(e, r, i, !0, o, e.ordered ?? !1)) : e.type === n.ListItem ? (l(), a(e, r, i, !0, o, s)) : c.push(e);
572
+ l();
573
+ } else if (t.content) {
574
+ let n = c.content?.textAlignment ?? "left";
575
+ w.renderText(e, t.content, i, p, i.Y, h, n === "justify");
576
+ }
577
+ }, O = (e, t, n, r, i, a, o, s, c = !0) => {
578
+ if (t?.items && t?.items.length > 0) for (let e of t?.items ?? []) a(e, n, r, i, o, s, c);
579
+ else {
580
+ let a = r.options, l = n * a.page.indent, u = i ? s ? `${o}. ` : "• " : "", d = t.content || "", f = a.page.xpading;
581
+ if (!d && !u) return;
582
+ if (!d.trim() && !u) {
583
+ let t = (d.match(/\n/g) || []).length;
584
+ if (t > 1) {
585
+ let n = (t - 1) * (e.getTextDimensions("A").h * a.page.defaultLineHeightFactor);
586
+ r.Y + n > a.page.maxContentHeight ? _(e, r) : (r.updateY(n, "add"), r.recordContentY(r.Y));
587
+ }
588
+ return;
589
+ }
590
+ if (r.updateX(f, "set"), i && u) {
591
+ let t = e.getTextWidth(u), n = a.page.maxContentWidth - l - t;
592
+ e.setFont(a.font.regular.name, a.font.regular.style), e.text(u, f + l, r.Y, { baseline: "top" }), w.renderText(e, d, r, f + l + t, r.Y, n, c);
593
+ } else {
594
+ let t = a.page.maxContentWidth - l;
595
+ w.renderText(e, d, r, f + l, r.Y, t, c);
596
+ }
597
+ r.updateX(f, "set");
598
+ }
599
+ }, k = (e, t) => {
600
+ let n = e.internal.pageSize.getWidth();
601
+ e.setLineDashPattern([1, 1], 0), e.setLineWidth(.1), e.line(t.options.page.xpading, t.Y, n - t.options.page.xpading, t.Y), e.setLineWidth(.1), e.setLineDashPattern([], 0), t.updateY(m(e), "add");
602
+ }, A = (e, t, n, r) => {
603
+ let i = e.getFont(), a = e.getFontSize();
604
+ e.setFont("courier", "normal");
605
+ let o = r.options.page.defaultFontSize * .9;
606
+ e.setFontSize(o);
607
+ let s = n * r.options.page.indent, c = r.options.page.maxContentWidth - s - 8, l = e.getLineHeightFactor(), u = o / e.internal.scaleFactor * l, d = (t.code ?? "").replace(/[\r\n\s]+$/, "");
608
+ if (!d) {
609
+ e.setFont(i.fontName, i.fontStyle), e.setFontSize(a);
610
+ return;
611
+ }
612
+ let f = e.splitTextToSize(d, c);
613
+ for (; f.length > 0 && f[f.length - 1].trim() === "";) f.pop();
614
+ if (f.length === 0) {
615
+ e.setFont(i.fontName, i.fontStyle), e.setFontSize(a);
616
+ return;
617
+ }
618
+ let p = 0;
619
+ for (; p < f.length;) {
620
+ let n = r.options.page.maxContentHeight - r.Y, i = f.length - p, a = n - 8, o = Math.floor(a / u);
621
+ if (o <= 0) {
622
+ _(e, r);
623
+ continue;
624
+ }
625
+ o > i && (o = i);
626
+ let s = f.slice(p, p + o), c = p === 0, l = p + o >= f.length, d = o * u;
627
+ if (c && r.updateY(4, "add"), e.setFillColor("#EEEEEE"), e.setDrawColor("#DDDDDD"), e.roundedRect(r.X, r.Y - 4, r.options.page.maxContentWidth, d + (c ? 4 : 0) + (l ? 4 : 0), 2, 2, "FD"), c && t.lang) {
628
+ let n = e.getFontSize();
629
+ e.setFontSize(10), e.setTextColor("#666666"), e.text(t.lang, r.X + r.options.page.maxContentWidth - e.getTextWidth(t.lang) - 4, r.Y, { baseline: "top" }), e.setFontSize(n), e.setTextColor("#000000");
630
+ }
631
+ let m = r.Y;
632
+ for (let t of s) e.text(t, r.X + 4, m, { baseline: "top" }), m += u;
633
+ r.updateY(d, "add"), r.recordContentY(r.Y + (l ? 4 : 0)), l && r.updateY(4, "add"), p += o, p < f.length && _(e, r);
634
+ }
635
+ e.setFont(i.fontName, i.fontStyle), e.setFontSize(a);
636
+ }, j = (e, t, n, r) => {
637
+ let i = e.getFont().fontName, a = e.getFont().fontStyle, o = e.getFontSize(), s = (e) => {
638
+ switch (e) {
639
+ case "normal": return 0;
640
+ case "bold": return 1;
641
+ case "italic": return 1.5;
642
+ case "bolditalic": return 1.5;
643
+ case "codespan": return .5;
644
+ default: return 0;
645
+ }
646
+ }, c = (t, c) => {
647
+ c === "bold" ? e.setFont(r.options.font.bold.name && r.options.font.bold.name !== "" ? r.options.font.bold.name : i, r.options.font.bold.style || "bold") : c === "italic" ? e.setFont(r.options.font.regular.name, "italic") : c === "bolditalic" ? e.setFont(r.options.font.bold.name && r.options.font.bold.name !== "" ? r.options.font.bold.name : i, "bolditalic") : c === "codespan" ? (e.setFont("courier", "normal"), e.setFontSize(o * .9)) : e.setFont(r.options.font.regular.name, a);
648
+ let l = r.options.page.maxContentWidth - n - r.X, u = e.splitTextToSize(t, l), d = c === "codespan", f = "#EEEEEE";
649
+ if (r.isInlineLockActive) for (let t = 0; t < u.length; t++) {
650
+ if (d) {
651
+ let i = e.getTextWidth(u[t]) + h(e), a = m(e);
652
+ e.setFillColor(f), e.roundedRect(r.X + n - 1, r.Y - 1, i + 2, a + 2, 2, 2, "F"), e.setFillColor("#000000");
653
+ }
654
+ e.text(u[t], r.X + n, r.Y, {
655
+ baseline: "top",
656
+ maxWidth: l
657
+ }), r.updateX(e.getTextDimensions(u[t]).w + (d ? 2 : 1), "add"), t < u.length - 1 && (r.updateY(m(e), "add"), r.updateX(r.options.page.xpading, "set"));
658
+ }
659
+ else if (u.length > 1) {
660
+ let t = u[0], i = u?.slice(1)?.join(" ");
661
+ if (d) {
662
+ let i = e.getTextWidth(t) + h(e), a = m(e);
663
+ e.setFillColor(f), e.roundedRect(r.X + (n >= 2 ? n + 2 : 0) - 1, r.Y - 1, i + 2, a + 2, 2, 2, "F"), e.setFillColor("#000000");
664
+ }
665
+ e.text(t, r.X + (n >= 2 ? n + 2 * s(c) : 0), r.Y, {
666
+ baseline: "top",
667
+ maxWidth: l
668
+ }), r.updateX(r.options.page.xpading + n), r.updateY(m(e), "add");
669
+ let a = r.options.page.maxContentWidth - n - r.options.page.xpading;
670
+ e.splitTextToSize(i, a).forEach((t) => {
671
+ if (d) {
672
+ let n = e.getTextWidth(t) + h(e), i = m(e);
673
+ e.setFillColor(f), e.roundedRect(r.X + h(e) - 1, r.Y - 1, n + 2, i + 2, 2, 2, "F"), e.setFillColor("#000000");
674
+ }
675
+ e.text(t, r.X + h(e), r.Y, {
676
+ baseline: "top",
677
+ maxWidth: a
678
+ });
679
+ });
680
+ } else {
681
+ if (d) {
682
+ let i = e.getTextWidth(t) + h(e), a = m(e);
683
+ e.setFillColor(f), e.roundedRect(r.X + n - 1, r.Y - 1, i + 2, a + 2, 2, 2, "F"), e.setFillColor("#000000");
684
+ }
685
+ e.text(t, r.X + n, r.Y, {
686
+ baseline: "top",
687
+ maxWidth: l
688
+ }), r.updateX(e.getTextDimensions(t).w + (n >= 2 ? t.split(" ").length + 2 : 2) * s(c) * .5 + (d ? 2 : 0), "add");
689
+ }
690
+ };
691
+ if (t.type === "text" && t.items && t.items.length > 0) for (let e of t.items) if (e.type === "codespan") c(e.content || "", "codespan");
692
+ else if (e.type === "em" || e.type === "strong") {
693
+ let t = e.type === "em" ? "italic" : "bold";
694
+ if (e.items && e.items.length > 0) for (let n of e.items) n.type === "strong" && t === "italic" || n.type === "em" && t === "bold" ? c(n.content || "", "bolditalic") : c(n.content || "", t);
695
+ else c(e.content || "", t);
696
+ } else c(e.content || "", "normal");
697
+ else t.type === "em" ? c(t.content || "", "italic") : t.type === "strong" ? c(t.content || "", "bold") : t.type === "codespan" ? c(t.content || "", "codespan") : c(t.content || "", "normal");
698
+ e.setFont(i, a), e.setFontSize(o);
699
+ }, M = (e, t, n, r) => {
700
+ let i = e.getFont().fontName, a = e.getFont().fontStyle, o = e.getFontSize(), s = e.getTextColor(), c = r.options.link?.linkColor || [
701
+ 0,
702
+ 0,
703
+ 255
704
+ ];
705
+ e.setTextColor(...c);
706
+ let l = r.options.page.maxContentWidth - n - r.X, u = t.text || t.content || "", d = t.href || "", f = e.splitTextToSize(u, l);
707
+ if (r.isInlineLockActive) for (let t = 0; t < f.length; t++) {
708
+ let i = e.getTextDimensions(f[t]).w, a = m(e) / 2;
709
+ e.link(r.X + n, r.Y, i, a, { url: d }), e.text(f[t], r.X + n, r.Y, {
710
+ baseline: "top",
711
+ maxWidth: l
712
+ }), r.updateX(i + 1, "add"), r.X + i > r.options.page.maxContentWidth - n && (r.updateY(a, "add"), r.updateX(r.options.page.xpading + n, "set")), t < f.length - 1 && (r.updateY(a, "add"), r.updateX(r.options.page.xpading + n, "set"));
713
+ }
714
+ else if (f.length > 1) {
715
+ let t = f[0], i = f?.slice(1)?.join(" "), a = e.getTextDimensions(t).w, o = m(e) / 2;
716
+ e.link(r.X + n, r.Y, a, o, { url: d }), e.text(t, r.X + n, r.Y, {
717
+ baseline: "top",
718
+ maxWidth: l
719
+ }), r.updateX(r.options.page.xpading + n), r.updateY(o, "add");
720
+ let s = r.options.page.maxContentWidth - n - r.options.page.xpading;
721
+ e.splitTextToSize(i, s).forEach((t) => {
722
+ let n = e.getTextDimensions(t).w;
723
+ e.link(r.X + h(e), r.Y, n, o, { url: d }), e.text(t, r.X + h(e), r.Y, {
724
+ baseline: "top",
725
+ maxWidth: s
726
+ });
727
+ });
728
+ } else {
729
+ let t = e.getTextDimensions(u).w, i = m(e) / 2;
730
+ e.link(r.X + n, r.Y, t, i, { url: d }), e.text(u, r.X + n, r.Y, {
731
+ baseline: "top",
732
+ maxWidth: l
733
+ }), r.updateX(t + 2, "add");
734
+ }
735
+ e.setFont(i, a), e.setFontSize(o), e.setTextColor(s);
736
+ }, N = (e, t, n, r, i) => {
737
+ let a = r.options, o = n + 1, s = r.X + n * a.page.indent, c = r.Y, l = s + a.page.indent / 2, u = c, d = e.internal.getCurrentPageInfo().pageNumber;
738
+ t.items && t.items.length > 0 && t.items.forEach((e) => {
739
+ i(e, o, r);
740
+ });
741
+ let f = r.Y, p = e.internal.getCurrentPageInfo().pageNumber;
742
+ e.setDrawColor(100), e.setLineWidth(1);
743
+ for (let t = d; t <= p; t++) {
744
+ e.setPage(t);
745
+ let n = t === d, r = t === p, i = n ? u : a.page.topmargin, o = r ? f : a.page.maxContentHeight;
746
+ e.line(l, i, l, o);
747
+ }
748
+ r.recordContentY(), e.setPage(p);
749
+ }, P = (e) => {
750
+ if (e.data) {
751
+ if (e.data.startsWith("data:image/png")) return "PNG";
752
+ if (e.data.startsWith("data:image/jpeg") || e.data.startsWith("data:image/jpg")) return "JPEG";
753
+ if (e.data.startsWith("data:image/webp") || e.data.startsWith("data:image/webp")) return "WEBP";
754
+ if (e.data.startsWith("data:image/gif")) return "GIF";
755
+ }
756
+ if (e.src) {
757
+ let t = e.src.split("?")[0].split("#")[0].split(".").pop()?.toUpperCase();
758
+ if (t && [
759
+ "PNG",
760
+ "JPEG",
761
+ "JPG",
762
+ "WEBP",
763
+ "GIF"
764
+ ].includes(t)) return t === "JPG" ? "JPEG" : t;
765
+ }
766
+ return "JPEG";
767
+ }, F = (e, t, n, r) => {
768
+ if (!t.data) return;
769
+ let i = r.options, a = i.page.unit || "mm", o = n * i.page.indent, s = i.page.maxContentWidth - o, c = r.X + o, l = r.Y;
770
+ try {
771
+ let { finalWidth: n, finalHeight: o } = x(e, t, s, i.page.maxContentHeight - i.page.topmargin, a);
772
+ l + o > i.page.maxContentHeight && (_(e, r), l = r.Y);
773
+ let u = t.align || i.image?.defaultAlign || "left", d;
774
+ switch (u) {
775
+ case "right":
776
+ d = c + s - n;
777
+ break;
778
+ case "center":
779
+ d = c + (s - n) / 2;
780
+ break;
781
+ default:
782
+ d = c;
783
+ break;
784
+ }
785
+ let f = P(t);
786
+ n > 0 && o > 0 && e.addImage(t.data, f, d, l, n, o), r.updateY(o, "add"), r.recordContentY();
787
+ } catch (e) {
788
+ console.warn("Failed to render image", e);
789
+ }
790
+ }, I = () => {
791
+ let e = t;
792
+ if (typeof t == "function") return t;
793
+ if (typeof e.default == "function") return e.default;
794
+ if (typeof e.autoTable == "function") return e.autoTable;
795
+ throw Error("Could not resolve jspdf-autotable export. Expected a callable export.");
796
+ }, L = (e, t, n, r) => {
797
+ if (!t.header || !t.rows) return;
798
+ let i = r.options, a = i.page.xmargin + n * i.page.indent, o = [t.header.map((e) => e.content || "")], s = t.rows.map((e) => e.map((e) => e.content || "")), c = i.table || {};
799
+ I()(e, {
800
+ head: o,
801
+ body: s,
802
+ startY: r.Y,
803
+ margin: {
804
+ left: a,
805
+ right: i.page.xmargin
806
+ },
807
+ ...c,
808
+ didDrawPage: (e) => {
809
+ c.didDrawPage && c.didDrawPage(e);
810
+ },
811
+ didDrawCell: (e) => {
812
+ c.didDrawCell && c.didDrawCell(e);
813
+ }
814
+ });
815
+ let l = e.lastAutoTable?.finalY;
816
+ typeof l == "number" && (r.updateY(l + i.page.lineSpace, "set"), r.updateX(i.page.xpading, "set"), r.recordContentY());
817
+ }, R = class {
818
+ constructor(e) {
819
+ this.cursor = {
820
+ x: 0,
821
+ y: 0
822
+ }, this.lastContentY_ = 0, this.inlineLock = !1, this.options_ = e, this.cursor = {
823
+ x: e.cursor.x,
824
+ y: e.cursor.y
825
+ }, this.lastContentY_ = e.cursor.y;
826
+ }
827
+ getCursor() {
828
+ return this.cursor;
829
+ }
830
+ setCursor(e) {
831
+ this.cursor = e;
832
+ }
833
+ get options() {
834
+ return this.options_;
835
+ }
836
+ get isInlineLockActive() {
837
+ return this.inlineLock;
838
+ }
839
+ activateInlineLock() {
840
+ this.inlineLock = !0;
841
+ }
842
+ deactivateInlineLock() {
843
+ this.inlineLock = !1;
844
+ }
845
+ updateX(e, t = "set") {
846
+ t === "set" ? this.cursor.x = e : t === "add" && (this.cursor.x += e);
847
+ }
848
+ updateY(e, t = "set") {
849
+ t === "set" ? this.cursor.y = e : t === "add" && (this.cursor.y += e);
850
+ }
851
+ recordContentY(e) {
852
+ this.lastContentY_ = e === void 0 ? this.cursor.y : e;
853
+ }
854
+ get lastContentY() {
855
+ return this.lastContentY_;
856
+ }
857
+ get X() {
858
+ return this.cursor.x;
859
+ }
860
+ get Y() {
861
+ return this.cursor.y;
862
+ }
863
+ }, z = {
864
+ page: {
865
+ indent: 10,
866
+ maxContentWidth: 190,
867
+ maxContentHeight: 277,
868
+ lineSpace: 1.5,
869
+ defaultLineHeightFactor: 1.2,
870
+ defaultFontSize: 12,
871
+ defaultTitleFontSize: 14,
872
+ topmargin: 10,
873
+ xpading: 10,
874
+ xmargin: 10,
875
+ format: "a4",
876
+ orientation: "p"
877
+ },
878
+ font: {
879
+ bold: {
880
+ name: "helvetica",
881
+ style: "bold"
882
+ },
883
+ regular: {
884
+ name: "helvetica",
885
+ style: "normal"
886
+ },
887
+ light: {
888
+ name: "helvetica",
889
+ style: "light"
890
+ }
891
+ },
892
+ image: { defaultAlign: "left" }
893
+ }, B = (e) => {
894
+ if (!e) throw Error("RenderOption is required");
895
+ let t = {
896
+ ...z.page,
897
+ ...e.page
898
+ }, n = {
899
+ ...z.font,
900
+ ...e.font
901
+ }, r = {
902
+ ...z.image,
903
+ ...e.image
904
+ };
905
+ return t.maxContentWidth ||= 190, t.maxContentHeight ||= 277, {
906
+ ...e,
907
+ page: t,
908
+ font: n,
909
+ image: r
910
+ };
911
+ }, V = async (e, t, r) => {
912
+ let i = B(r), a = new R(i), o = await d(t);
913
+ await S(o);
914
+ let s = (t, r = 0, a, o = !1, c = 0, l = !1) => {
915
+ let u = r * i.page.indent;
916
+ switch (t.type) {
917
+ case n.Heading:
918
+ g(e, t, u, a, s);
919
+ break;
920
+ case n.Paragraph:
921
+ T(e, t, u, a, s);
922
+ break;
923
+ case n.List:
924
+ E(e, t, r, a, s);
925
+ break;
926
+ case n.ListItem:
927
+ D(e, t, r, a, s, c, l);
928
+ break;
929
+ case n.Hr:
930
+ k(e, a);
931
+ break;
932
+ case n.Code:
933
+ A(e, t, r, a);
934
+ break;
935
+ case n.Strong:
936
+ case n.Em:
937
+ case n.CodeSpan:
938
+ j(e, t, u, a);
939
+ break;
940
+ case n.Link:
941
+ M(e, t, u, a);
942
+ break;
943
+ case n.Blockquote:
944
+ N(e, t, r, a, s);
945
+ break;
946
+ case n.Image:
947
+ F(e, t, r, a);
948
+ break;
949
+ case n.Br: {
950
+ a.updateX(i.page.xpading, "set");
951
+ let t = m(e) * i.page.defaultLineHeightFactor;
952
+ a.Y + t > i.page.maxContentHeight ? _(e, a) : a.updateY(t, "add"), a.recordContentY();
953
+ break;
954
+ }
955
+ case n.Table:
956
+ L(e, t, r, a);
957
+ break;
958
+ case n.Raw:
959
+ case n.Text:
960
+ O(e, t, r, a, o, s, c, l, i.content?.textAlignment === "justify");
961
+ break;
962
+ default:
963
+ console.warn(`Warning: Unsupported element type encountered: ${t.type}.
1325
964
  If you believe this element type should be supported, please create an issue at:
1326
965
  https://github.com/JeelGajera/jspdf-md-renderer/issues
1327
- with details of the element and expected behavior. Thanks for helping to improve this library!`
1328
- );
1329
- break;
1330
- }
1331
- };
1332
- for (const g of c)
1333
- o(g);
1334
- r.endCursorYHandler(n.Y);
1335
- };
1336
- export {
1337
- K as MdTextParser,
1338
- xt as MdTextRender
966
+ with details of the element and expected behavior. Thanks for helping to improve this library!`);
967
+ break;
968
+ }
969
+ };
970
+ for (let e of o) s(e, 0, a);
971
+ i.endCursorYHandler(a.Y);
1339
972
  };
973
+ //#endregion
974
+ export { d as MdTextParser, V as MdTextRender };