@pyreon/document 0.10.0 → 0.11.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/lib/analysis/index.js.html +1 -1
- package/lib/confluence-Bd3ua1Ut.js.map +1 -1
- package/lib/csv-COrS4qdy.js.map +1 -1
- package/lib/discord-BLUnkEh9.js.map +1 -1
- package/lib/{dist-BsqdI2nY.js → dist-CYL41kqQ.js} +2 -2
- package/lib/dist-CYL41kqQ.js.map +1 -0
- package/lib/{docx-BEBOihjl.js → docx-uNAel545.js} +7 -2
- package/lib/docx-uNAel545.js.map +1 -0
- package/lib/email-D0bbfWq4.js.map +1 -1
- package/lib/{exceljs-BoIDUUaw.js → exceljs-BYETsesT.js} +314 -314
- package/lib/exceljs-BYETsesT.js.map +1 -0
- package/lib/google-chat-CkKCBUWC.js.map +1 -1
- package/lib/html-B5biprN2.js.map +1 -1
- package/lib/index.js +17 -8
- package/lib/index.js.map +1 -1
- package/lib/markdown-CdtlFGC0.js.map +1 -1
- package/lib/notion-iG2C5bEY.js.map +1 -1
- package/lib/{pdf-DIUQUEdj.js → pdf-IuBgTb3T.js} +9 -3
- package/lib/pdf-IuBgTb3T.js.map +1 -0
- package/lib/{pdfmake-DnmLxK4Q.js → pdfmake-CKMX5URW.js} +2 -4
- package/lib/pdfmake-CKMX5URW.js.map +1 -0
- package/lib/{pptx-Dd33oL3_.js → pptx-DXiMiYFM.js} +7 -2
- package/lib/pptx-DXiMiYFM.js.map +1 -0
- package/lib/{pptxgen.es-COcgXsyx.js → pptxgen.es-FsqHs8mD.js} +3 -6
- package/lib/pptxgen.es-FsqHs8mD.js.map +1 -0
- package/lib/sanitize-O_3j1mNJ.js.map +1 -1
- package/lib/slack-BI3EQwYm.js.map +1 -1
- package/lib/svg-BKxumy-p.js.map +1 -1
- package/lib/teams-Cwz9lce0.js.map +1 -1
- package/lib/telegram-gYFqyMXb.js.map +1 -1
- package/lib/text-l1XNXBOC.js.map +1 -1
- package/lib/types/index.d.ts +43 -39
- package/lib/types/index.d.ts.map +1 -1
- package/lib/{vfs_fonts-Df1kkZ4Y.js → vfs_fonts-Cap07Jg3.js} +2 -2
- package/lib/vfs_fonts-Cap07Jg3.js.map +1 -0
- package/lib/whatsapp-CjSGoOKx.js.map +1 -1
- package/lib/{xlsx-Bb5TWyXQ.js → xlsx-Cvu4LBNy.js} +8 -2
- package/lib/xlsx-Cvu4LBNy.js.map +1 -0
- package/package.json +19 -7
- package/src/builder.ts +53 -44
- package/src/download.ts +32 -36
- package/src/env.d.ts +3 -17
- package/src/index.ts +6 -8
- package/src/nodes.ts +45 -45
- package/src/render.ts +45 -118
- package/src/renderers/confluence.ts +64 -80
- package/src/renderers/csv.ts +11 -18
- package/src/renderers/discord.ts +38 -50
- package/src/renderers/docx.ts +78 -120
- package/src/renderers/email.ts +73 -92
- package/src/renderers/google-chat.ts +35 -47
- package/src/renderers/html.ts +78 -101
- package/src/renderers/markdown.ts +43 -53
- package/src/renderers/notion.ts +63 -85
- package/src/renderers/pdf.ts +92 -115
- package/src/renderers/pptx.ts +60 -66
- package/src/renderers/slack.ts +49 -61
- package/src/renderers/svg.ts +49 -63
- package/src/renderers/teams.ts +68 -80
- package/src/renderers/telegram.ts +40 -54
- package/src/renderers/text.ts +44 -66
- package/src/renderers/whatsapp.ts +34 -48
- package/src/renderers/xlsx.ts +47 -61
- package/src/sanitize.ts +21 -25
- package/src/tests/document.test.ts +1337 -1385
- package/src/tests/stress.test.ts +111 -111
- package/src/types.ts +66 -65
- package/lib/dist-BsqdI2nY.js.map +0 -1
- package/lib/docx-BEBOihjl.js.map +0 -1
- package/lib/exceljs-BoIDUUaw.js.map +0 -1
- package/lib/pdf-DIUQUEdj.js.map +0 -1
- package/lib/pdfmake-DnmLxK4Q.js.map +0 -1
- package/lib/pptx-Dd33oL3_.js.map +0 -1
- package/lib/pptxgen.es-COcgXsyx.js.map +0 -1
- package/lib/vfs_fonts-Df1kkZ4Y.js.map +0 -1
- package/lib/xlsx-Bb5TWyXQ.js.map +0 -1
package/src/renderers/pdf.ts
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
DocChild,
|
|
3
|
-
DocNode,
|
|
4
|
-
DocumentRenderer,
|
|
5
|
-
RenderOptions,
|
|
6
|
-
TableColumn,
|
|
7
|
-
} from '../types'
|
|
1
|
+
import type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } from "../types"
|
|
8
2
|
|
|
9
3
|
/**
|
|
10
4
|
* PDF renderer — lazy-loads pdfmake on first use.
|
|
@@ -23,15 +17,13 @@ import type {
|
|
|
23
17
|
*/
|
|
24
18
|
|
|
25
19
|
function resolveColumn(col: string | TableColumn): TableColumn {
|
|
26
|
-
return typeof col ===
|
|
20
|
+
return typeof col === "string" ? { header: col } : col
|
|
27
21
|
}
|
|
28
22
|
|
|
29
23
|
function getTextContent(children: DocChild[]): string {
|
|
30
24
|
return children
|
|
31
|
-
.map((c) =>
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
.join('')
|
|
25
|
+
.map((c) => (typeof c === "string" ? c : getTextContent((c as DocNode).children)))
|
|
26
|
+
.join("")
|
|
35
27
|
}
|
|
36
28
|
|
|
37
29
|
type PdfContent = Record<string, unknown> | string | PdfContent[]
|
|
@@ -58,42 +50,39 @@ const PAGE_SIZES: Record<string, { width: number; height: number }> = {
|
|
|
58
50
|
function resolveImageSrc(
|
|
59
51
|
src: string,
|
|
60
52
|
): { image: string } | { text: string; italics: true; color: string } {
|
|
61
|
-
if (src.startsWith(
|
|
53
|
+
if (src.startsWith("data:")) {
|
|
62
54
|
return { image: src }
|
|
63
55
|
}
|
|
64
|
-
if (src.startsWith(
|
|
65
|
-
return { text: `[Image: ${src}]`, italics: true, color:
|
|
56
|
+
if (src.startsWith("http://") || src.startsWith("https://")) {
|
|
57
|
+
return { text: `[Image: ${src}]`, italics: true, color: "#999999" }
|
|
66
58
|
}
|
|
67
59
|
// Local path — cannot resolve in browser
|
|
68
|
-
return { text: `[Image: ${src}]`, italics: true, color:
|
|
60
|
+
return { text: `[Image: ${src}]`, italics: true, color: "#999999" }
|
|
69
61
|
}
|
|
70
62
|
|
|
71
63
|
function nodeToContent(node: DocNode): PdfContent | PdfContent[] | null {
|
|
72
64
|
const p = node.props
|
|
73
65
|
|
|
74
66
|
switch (node.type) {
|
|
75
|
-
case
|
|
76
|
-
case
|
|
67
|
+
case "document":
|
|
68
|
+
case "page":
|
|
77
69
|
return node.children
|
|
78
|
-
.map((c) => (typeof c ===
|
|
70
|
+
.map((c) => (typeof c === "string" ? c : nodeToContent(c)))
|
|
79
71
|
.filter((c): c is PdfContent => c != null)
|
|
80
72
|
|
|
81
|
-
case
|
|
73
|
+
case "section": {
|
|
82
74
|
const content = node.children
|
|
83
|
-
.map((c) => (typeof c ===
|
|
75
|
+
.map((c) => (typeof c === "string" ? c : nodeToContent(c)))
|
|
84
76
|
.filter((c): c is PdfContent => c != null)
|
|
85
77
|
.flat()
|
|
86
78
|
|
|
87
|
-
if (p.direction ===
|
|
79
|
+
if (p.direction === "row") {
|
|
88
80
|
return {
|
|
89
81
|
columns: node.children
|
|
90
|
-
.filter((c): c is DocNode => typeof c !==
|
|
82
|
+
.filter((c): c is DocNode => typeof c !== "string")
|
|
91
83
|
.map((child) => ({
|
|
92
84
|
stack: [nodeToContent(child)].flat().filter(Boolean),
|
|
93
|
-
width:
|
|
94
|
-
child.props.width === '*' || !child.props.width
|
|
95
|
-
? '*'
|
|
96
|
-
: child.props.width,
|
|
85
|
+
width: child.props.width === "*" || !child.props.width ? "*" : child.props.width,
|
|
97
86
|
})),
|
|
98
87
|
columnGap: (p.gap as number) ?? 0,
|
|
99
88
|
}
|
|
@@ -102,25 +91,25 @@ function nodeToContent(node: DocNode): PdfContent | PdfContent[] | null {
|
|
|
102
91
|
return content
|
|
103
92
|
}
|
|
104
93
|
|
|
105
|
-
case
|
|
94
|
+
case "row": {
|
|
106
95
|
return {
|
|
107
96
|
columns: node.children
|
|
108
|
-
.filter((c): c is DocNode => typeof c !==
|
|
97
|
+
.filter((c): c is DocNode => typeof c !== "string")
|
|
109
98
|
.map((child) => ({
|
|
110
99
|
stack: [nodeToContent(child)].flat().filter(Boolean),
|
|
111
|
-
width: child.props.width ??
|
|
100
|
+
width: child.props.width ?? "*",
|
|
112
101
|
})),
|
|
113
102
|
columnGap: (p.gap as number) ?? 0,
|
|
114
103
|
}
|
|
115
104
|
}
|
|
116
105
|
|
|
117
|
-
case
|
|
106
|
+
case "column":
|
|
118
107
|
return node.children
|
|
119
|
-
.map((c) => (typeof c ===
|
|
108
|
+
.map((c) => (typeof c === "string" ? c : nodeToContent(c)))
|
|
120
109
|
.filter((c): c is PdfContent => c != null)
|
|
121
110
|
.flat()
|
|
122
111
|
|
|
123
|
-
case
|
|
112
|
+
case "heading": {
|
|
124
113
|
const level = (p.level as number) ?? 1
|
|
125
114
|
const sizes: Record<number, number> = {
|
|
126
115
|
1: 24,
|
|
@@ -134,49 +123,45 @@ function nodeToContent(node: DocNode): PdfContent | PdfContent[] | null {
|
|
|
134
123
|
text: getTextContent(node.children),
|
|
135
124
|
fontSize: sizes[level] ?? 18,
|
|
136
125
|
bold: true,
|
|
137
|
-
color: (p.color as string) ??
|
|
138
|
-
alignment: (p.align as string) ??
|
|
126
|
+
color: (p.color as string) ?? "#000000",
|
|
127
|
+
alignment: (p.align as string) ?? "left",
|
|
139
128
|
margin: [0, level === 1 ? 0 : 8, 0, 8],
|
|
140
129
|
}
|
|
141
130
|
}
|
|
142
131
|
|
|
143
|
-
case
|
|
132
|
+
case "text":
|
|
144
133
|
return {
|
|
145
134
|
text: getTextContent(node.children),
|
|
146
135
|
fontSize: (p.size as number) ?? 12,
|
|
147
|
-
color: (p.color as string) ??
|
|
136
|
+
color: (p.color as string) ?? "#333333",
|
|
148
137
|
bold: p.bold ?? false,
|
|
149
138
|
italics: p.italic ?? false,
|
|
150
|
-
decoration: p.underline
|
|
151
|
-
|
|
152
|
-
: p.strikethrough
|
|
153
|
-
? 'lineThrough'
|
|
154
|
-
: undefined,
|
|
155
|
-
alignment: (p.align as string) ?? 'left',
|
|
139
|
+
decoration: p.underline ? "underline" : p.strikethrough ? "lineThrough" : undefined,
|
|
140
|
+
alignment: (p.align as string) ?? "left",
|
|
156
141
|
lineHeight: (p.lineHeight as number) ?? 1.4,
|
|
157
142
|
margin: [0, 0, 0, 8],
|
|
158
143
|
}
|
|
159
144
|
|
|
160
|
-
case
|
|
145
|
+
case "link":
|
|
161
146
|
return {
|
|
162
147
|
text: getTextContent(node.children),
|
|
163
148
|
link: p.href as string,
|
|
164
|
-
color: (p.color as string) ??
|
|
165
|
-
decoration:
|
|
149
|
+
color: (p.color as string) ?? "#4f46e5",
|
|
150
|
+
decoration: "underline",
|
|
166
151
|
}
|
|
167
152
|
|
|
168
|
-
case
|
|
153
|
+
case "image": {
|
|
169
154
|
const src = p.src as string
|
|
170
155
|
const resolved = resolveImageSrc(src)
|
|
171
156
|
|
|
172
|
-
if (
|
|
157
|
+
if ("image" in resolved) {
|
|
173
158
|
const result: Record<string, unknown> = {
|
|
174
159
|
image: resolved.image,
|
|
175
160
|
fit: [p.width ?? 500, p.height ?? 400],
|
|
176
161
|
margin: [0, 0, 0, 8],
|
|
177
162
|
}
|
|
178
|
-
if (p.align ===
|
|
179
|
-
if (p.align ===
|
|
163
|
+
if (p.align === "center") result.alignment = "center"
|
|
164
|
+
if (p.align === "right") result.alignment = "right"
|
|
180
165
|
return result
|
|
181
166
|
}
|
|
182
167
|
|
|
@@ -184,34 +169,30 @@ function nodeToContent(node: DocNode): PdfContent | PdfContent[] | null {
|
|
|
184
169
|
return { ...resolved, margin: [0, 0, 0, 8] }
|
|
185
170
|
}
|
|
186
171
|
|
|
187
|
-
case
|
|
188
|
-
const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(
|
|
189
|
-
resolveColumn,
|
|
190
|
-
)
|
|
172
|
+
case "table": {
|
|
173
|
+
const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(resolveColumn)
|
|
191
174
|
const rows = (p.rows ?? []) as (string | number)[][]
|
|
192
|
-
const hs = p.headerStyle as
|
|
193
|
-
| { background?: string; color?: string }
|
|
194
|
-
| undefined
|
|
175
|
+
const hs = p.headerStyle as { background?: string; color?: string } | undefined
|
|
195
176
|
|
|
196
177
|
const headerRow = columns.map((col) => ({
|
|
197
178
|
text: col.header,
|
|
198
179
|
bold: true,
|
|
199
|
-
fillColor: hs?.background ??
|
|
200
|
-
color: hs?.color ??
|
|
201
|
-
alignment: col.align ??
|
|
180
|
+
fillColor: hs?.background ?? "#f5f5f5",
|
|
181
|
+
color: hs?.color ?? "#000000",
|
|
182
|
+
alignment: col.align ?? "left",
|
|
202
183
|
}))
|
|
203
184
|
|
|
204
185
|
const dataRows = rows.map((row, rowIdx) =>
|
|
205
186
|
columns.map((col, colIdx) => ({
|
|
206
|
-
text: String(row[colIdx] ??
|
|
207
|
-
alignment: col.align ??
|
|
208
|
-
fillColor: p.striped && rowIdx % 2 === 1 ?
|
|
187
|
+
text: String(row[colIdx] ?? ""),
|
|
188
|
+
alignment: col.align ?? "left",
|
|
189
|
+
fillColor: p.striped && rowIdx % 2 === 1 ? "#f9f9f9" : undefined,
|
|
209
190
|
})),
|
|
210
191
|
)
|
|
211
192
|
|
|
212
193
|
const widths = columns.map((col) => {
|
|
213
|
-
if (!col.width) return
|
|
214
|
-
if (typeof col.width ===
|
|
194
|
+
if (!col.width) return "*"
|
|
195
|
+
if (typeof col.width === "string" && col.width.endsWith("%")) {
|
|
215
196
|
return col.width
|
|
216
197
|
}
|
|
217
198
|
return col.width
|
|
@@ -223,83 +204,81 @@ function nodeToContent(node: DocNode): PdfContent | PdfContent[] | null {
|
|
|
223
204
|
widths,
|
|
224
205
|
body: [headerRow, ...dataRows],
|
|
225
206
|
},
|
|
226
|
-
layout: p.bordered ? undefined :
|
|
207
|
+
layout: p.bordered ? undefined : "lightHorizontalLines",
|
|
227
208
|
unbreakable: p.keepTogether ?? false,
|
|
228
209
|
margin: [0, 0, 0, 12],
|
|
229
210
|
}
|
|
230
211
|
}
|
|
231
212
|
|
|
232
|
-
case
|
|
213
|
+
case "list": {
|
|
233
214
|
const items = node.children
|
|
234
|
-
.filter((c): c is DocNode => typeof c !==
|
|
215
|
+
.filter((c): c is DocNode => typeof c !== "string")
|
|
235
216
|
.map((item) => getTextContent(item.children))
|
|
236
217
|
|
|
237
|
-
return p.ordered
|
|
238
|
-
? { ol: items, margin: [0, 0, 0, 8] }
|
|
239
|
-
: { ul: items, margin: [0, 0, 0, 8] }
|
|
218
|
+
return p.ordered ? { ol: items, margin: [0, 0, 0, 8] } : { ul: items, margin: [0, 0, 0, 8] }
|
|
240
219
|
}
|
|
241
220
|
|
|
242
|
-
case
|
|
221
|
+
case "list-item":
|
|
243
222
|
return getTextContent(node.children)
|
|
244
223
|
|
|
245
|
-
case
|
|
224
|
+
case "code":
|
|
246
225
|
return {
|
|
247
226
|
text: getTextContent(node.children),
|
|
248
|
-
font:
|
|
227
|
+
font: "Courier",
|
|
249
228
|
fontSize: 10,
|
|
250
|
-
background:
|
|
229
|
+
background: "#f5f5f5",
|
|
251
230
|
margin: [0, 0, 0, 8],
|
|
252
231
|
}
|
|
253
232
|
|
|
254
|
-
case
|
|
255
|
-
return { text:
|
|
233
|
+
case "page-break":
|
|
234
|
+
return { text: "", pageBreak: "after" }
|
|
256
235
|
|
|
257
|
-
case
|
|
236
|
+
case "divider":
|
|
258
237
|
return {
|
|
259
238
|
canvas: [
|
|
260
239
|
{
|
|
261
|
-
type:
|
|
240
|
+
type: "line",
|
|
262
241
|
x1: 0,
|
|
263
242
|
y1: 0,
|
|
264
243
|
x2: 515,
|
|
265
244
|
y2: 0,
|
|
266
245
|
lineWidth: (p.thickness as number) ?? 1,
|
|
267
|
-
lineColor: (p.color as string) ??
|
|
246
|
+
lineColor: (p.color as string) ?? "#dddddd",
|
|
268
247
|
},
|
|
269
248
|
],
|
|
270
249
|
margin: [0, 8, 0, 8],
|
|
271
250
|
}
|
|
272
251
|
|
|
273
|
-
case
|
|
274
|
-
return { text:
|
|
252
|
+
case "spacer":
|
|
253
|
+
return { text: "", margin: [0, (p.height as number) ?? 12, 0, 0] }
|
|
275
254
|
|
|
276
|
-
case
|
|
255
|
+
case "button":
|
|
277
256
|
return {
|
|
278
257
|
text: getTextContent(node.children),
|
|
279
258
|
link: p.href as string,
|
|
280
259
|
bold: true,
|
|
281
|
-
color: (p.color as string) ??
|
|
282
|
-
background: (p.background as string) ??
|
|
260
|
+
color: (p.color as string) ?? "#ffffff",
|
|
261
|
+
background: (p.background as string) ?? "#4f46e5",
|
|
283
262
|
margin: [0, 8, 0, 8],
|
|
284
263
|
}
|
|
285
264
|
|
|
286
|
-
case
|
|
265
|
+
case "quote":
|
|
287
266
|
return {
|
|
288
267
|
table: {
|
|
289
|
-
widths: [4,
|
|
268
|
+
widths: [4, "*"],
|
|
290
269
|
body: [
|
|
291
270
|
[
|
|
292
|
-
{ text:
|
|
271
|
+
{ text: "", fillColor: (p.borderColor as string) ?? "#dddddd" },
|
|
293
272
|
{
|
|
294
273
|
text: getTextContent(node.children),
|
|
295
274
|
italics: true,
|
|
296
|
-
color:
|
|
275
|
+
color: "#555555",
|
|
297
276
|
margin: [8, 4, 0, 4],
|
|
298
277
|
},
|
|
299
278
|
],
|
|
300
279
|
],
|
|
301
280
|
},
|
|
302
|
-
layout:
|
|
281
|
+
layout: "noBorders",
|
|
303
282
|
margin: [0, 4, 0, 8],
|
|
304
283
|
}
|
|
305
284
|
|
|
@@ -309,14 +288,10 @@ function nodeToContent(node: DocNode): PdfContent | PdfContent[] | null {
|
|
|
309
288
|
}
|
|
310
289
|
|
|
311
290
|
function resolveMargin(
|
|
312
|
-
margin:
|
|
313
|
-
| number
|
|
314
|
-
| [number, number]
|
|
315
|
-
| [number, number, number, number]
|
|
316
|
-
| undefined,
|
|
291
|
+
margin: number | [number, number] | [number, number, number, number] | undefined,
|
|
317
292
|
): [number, number, number, number] {
|
|
318
293
|
if (margin == null) return [40, 40, 40, 40]
|
|
319
|
-
if (typeof margin ===
|
|
294
|
+
if (typeof margin === "number") return [margin, margin, margin, margin]
|
|
320
295
|
if (margin.length === 2) return [margin[1], margin[0], margin[1], margin[0]]
|
|
321
296
|
return margin
|
|
322
297
|
}
|
|
@@ -332,23 +307,30 @@ function renderHeaderFooter(node: DocNode | undefined): PdfContent | undefined {
|
|
|
332
307
|
const content = nodeToContent(node)
|
|
333
308
|
if (content == null) return undefined
|
|
334
309
|
if (Array.isArray(content)) return { stack: content, margin: [40, 10, 40, 0] }
|
|
335
|
-
if (typeof content ===
|
|
336
|
-
return { ...content, margin: [40, 10, 40, 0] }
|
|
310
|
+
if (typeof content === "object") return { ...content, margin: [40, 10, 40, 0] }
|
|
337
311
|
return { text: content, margin: [40, 10, 40, 0] }
|
|
338
312
|
}
|
|
339
313
|
|
|
340
314
|
export const pdfRenderer: DocumentRenderer = {
|
|
341
315
|
async render(node: DocNode, _options?: RenderOptions): Promise<Uint8Array> {
|
|
342
316
|
// Lazy-load pdfmake — handle ESM/CJS interop
|
|
343
|
-
|
|
344
|
-
|
|
317
|
+
let pdfMakeModule: any
|
|
318
|
+
let pdfFontsModule: any
|
|
319
|
+
try {
|
|
320
|
+
pdfMakeModule = await import("pdfmake/build/pdfmake")
|
|
321
|
+
pdfFontsModule = await import("pdfmake/build/vfs_fonts")
|
|
322
|
+
} catch {
|
|
323
|
+
throw new Error(
|
|
324
|
+
'[@pyreon/document] PDF renderer requires "pdfmake" package. Install it: bun add pdfmake',
|
|
325
|
+
)
|
|
326
|
+
}
|
|
345
327
|
|
|
346
328
|
// Resolve the actual exports (handle .default for ESM wrappers).
|
|
347
329
|
// pdfmake's default export is a singleton instance of browser_extensions_pdfmake.
|
|
348
330
|
// ESM interop may wrap it in an extra .default layer.
|
|
349
331
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- pdfmake types are incomplete
|
|
350
332
|
let pdfMake: any = pdfMakeModule.default ?? pdfMakeModule
|
|
351
|
-
if (pdfMake.default && typeof pdfMake.default.createPdf ===
|
|
333
|
+
if (pdfMake.default && typeof pdfMake.default.createPdf === "function") {
|
|
352
334
|
pdfMake = pdfMake.default
|
|
353
335
|
}
|
|
354
336
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- pdfmake types are incomplete
|
|
@@ -361,11 +343,10 @@ export const pdfRenderer: DocumentRenderer = {
|
|
|
361
343
|
|
|
362
344
|
// Find page config
|
|
363
345
|
const pageNode = node.children.find(
|
|
364
|
-
(c): c is DocNode => typeof c !==
|
|
346
|
+
(c): c is DocNode => typeof c !== "string" && c.type === "page",
|
|
365
347
|
)
|
|
366
|
-
const pageSize = (pageNode?.props.size as string) ??
|
|
367
|
-
const pageOrientation =
|
|
368
|
-
(pageNode?.props.orientation as string) ?? 'portrait'
|
|
348
|
+
const pageSize = (pageNode?.props.size as string) ?? "A4"
|
|
349
|
+
const pageOrientation = (pageNode?.props.orientation as string) ?? "portrait"
|
|
369
350
|
const pageMargin = resolveMargin(
|
|
370
351
|
pageNode?.props.margin as
|
|
371
352
|
| number
|
|
@@ -377,22 +358,18 @@ export const pdfRenderer: DocumentRenderer = {
|
|
|
377
358
|
const content = [nodeToContent(node)].flat().filter(Boolean) as PdfContent[]
|
|
378
359
|
|
|
379
360
|
// Build header/footer from PageProps if present
|
|
380
|
-
const headerFn = renderHeaderFooter(
|
|
381
|
-
|
|
382
|
-
)
|
|
383
|
-
const footerFn = renderHeaderFooter(
|
|
384
|
-
pageNode?.props.footer as DocNode | undefined,
|
|
385
|
-
)
|
|
361
|
+
const headerFn = renderHeaderFooter(pageNode?.props.header as DocNode | undefined)
|
|
362
|
+
const footerFn = renderHeaderFooter(pageNode?.props.footer as DocNode | undefined)
|
|
386
363
|
|
|
387
364
|
const docDefinition: Record<string, unknown> = {
|
|
388
365
|
pageSize: PAGE_SIZES[pageSize] ?? PAGE_SIZES.A4,
|
|
389
366
|
pageOrientation,
|
|
390
367
|
pageMargins: pageMargin,
|
|
391
368
|
info: {
|
|
392
|
-
title: (node.props.title as string) ??
|
|
393
|
-
author: (node.props.author as string) ??
|
|
394
|
-
subject: (node.props.subject as string) ??
|
|
395
|
-
keywords: (node.props.keywords as string[])?.join(
|
|
369
|
+
title: (node.props.title as string) ?? "",
|
|
370
|
+
author: (node.props.author as string) ?? "",
|
|
371
|
+
subject: (node.props.subject as string) ?? "",
|
|
372
|
+
keywords: (node.props.keywords as string[])?.join(", ") ?? "",
|
|
396
373
|
},
|
|
397
374
|
content,
|
|
398
375
|
defaultStyle: {
|