@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/docx.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sanitizeHref, sanitizeXmlColor } from
|
|
1
|
+
import { sanitizeHref, sanitizeXmlColor } from "../sanitize"
|
|
2
2
|
import type {
|
|
3
3
|
DocChild,
|
|
4
4
|
DocNode,
|
|
@@ -7,22 +7,20 @@ import type {
|
|
|
7
7
|
PageSize,
|
|
8
8
|
RenderOptions,
|
|
9
9
|
TableColumn,
|
|
10
|
-
} from
|
|
10
|
+
} from "../types"
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* DOCX renderer — lazy-loads the 'docx' npm package on first use.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
function resolveColumn(col: string | TableColumn): TableColumn {
|
|
17
|
-
return typeof col ===
|
|
17
|
+
return typeof col === "string" ? { header: col } : col
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function getTextContent(children: DocChild[]): string {
|
|
21
21
|
return children
|
|
22
|
-
.map((c) =>
|
|
23
|
-
|
|
24
|
-
)
|
|
25
|
-
.join('')
|
|
22
|
+
.map((c) => (typeof c === "string" ? c : getTextContent((c as DocNode).children)))
|
|
23
|
+
.join("")
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
/** Parse a data URL and return the base64 data and media type, or null for external URLs. */
|
|
@@ -48,7 +46,7 @@ function getPageSize(
|
|
|
48
46
|
}
|
|
49
47
|
const dims = sizes[size]
|
|
50
48
|
if (!dims) return undefined
|
|
51
|
-
if (orientation ===
|
|
49
|
+
if (orientation === "landscape") {
|
|
52
50
|
return { width: dims.height, height: dims.width }
|
|
53
51
|
}
|
|
54
52
|
return dims
|
|
@@ -59,7 +57,7 @@ function getPageMargins(
|
|
|
59
57
|
margin?: number | [number, number] | [number, number, number, number],
|
|
60
58
|
): object | undefined {
|
|
61
59
|
if (margin == null) return undefined
|
|
62
|
-
if (typeof margin ===
|
|
60
|
+
if (typeof margin === "number") {
|
|
63
61
|
const twips = margin * 20
|
|
64
62
|
return { top: twips, right: twips, bottom: twips, left: twips }
|
|
65
63
|
}
|
|
@@ -80,27 +78,20 @@ function getPageMargins(
|
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
/** Map percentage column width to DOCX table column width. */
|
|
83
|
-
function getColumnWidth(
|
|
84
|
-
width?: number | string,
|
|
85
|
-
): { size: number; type: unknown } | undefined {
|
|
81
|
+
function getColumnWidth(width?: number | string): { size: number; type: unknown } | undefined {
|
|
86
82
|
if (width == null) return undefined
|
|
87
|
-
if (typeof width ===
|
|
83
|
+
if (typeof width === "number") return undefined
|
|
88
84
|
const match = width.match(/^(\d+)%$/)
|
|
89
85
|
if (!match) return undefined
|
|
90
|
-
return { size: Number.parseInt(match[1]!, 10) * 100, type:
|
|
86
|
+
return { size: Number.parseInt(match[1]!, 10) * 100, type: "pct" as unknown }
|
|
91
87
|
}
|
|
92
88
|
|
|
93
89
|
/** Shared context passed to per-node-type render helpers. */
|
|
94
90
|
interface DocxCtx {
|
|
95
|
-
docx: typeof import(
|
|
91
|
+
docx: typeof import("docx")
|
|
96
92
|
children: unknown[]
|
|
97
93
|
alignmentMap: (align?: string) => unknown
|
|
98
|
-
processListItems: (
|
|
99
|
-
n: DocNode,
|
|
100
|
-
listRef: string,
|
|
101
|
-
level: number,
|
|
102
|
-
ordered: boolean,
|
|
103
|
-
) => void
|
|
94
|
+
processListItems: (n: DocNode, listRef: string, level: number, ordered: boolean) => void
|
|
104
95
|
nextListId: () => string
|
|
105
96
|
}
|
|
106
97
|
|
|
@@ -142,11 +133,9 @@ function renderTextNode(ctx: DocxCtx, n: DocNode): void {
|
|
|
142
133
|
...(p.bold != null ? { bold: p.bold as boolean } : {}),
|
|
143
134
|
...(p.italic != null ? { italics: p.italic as boolean } : {}),
|
|
144
135
|
...(p.underline ? { underline: {} } : {}),
|
|
145
|
-
...(p.strikethrough != null
|
|
146
|
-
? { strike: p.strikethrough as boolean }
|
|
147
|
-
: {}),
|
|
136
|
+
...(p.strikethrough != null ? { strike: p.strikethrough as boolean } : {}),
|
|
148
137
|
...(p.size != null ? { size: (p.size as number) * 2 } : {}),
|
|
149
|
-
color: sanitizeXmlColor(p.color as string,
|
|
138
|
+
color: sanitizeXmlColor(p.color as string, "333333"),
|
|
150
139
|
}),
|
|
151
140
|
],
|
|
152
141
|
alignment: alignmentMap(p.align as string) as any,
|
|
@@ -166,7 +155,7 @@ function renderLink(ctx: DocxCtx, n: DocNode): void {
|
|
|
166
155
|
children: [
|
|
167
156
|
new docx.TextRun({
|
|
168
157
|
text: getTextContent(n.children),
|
|
169
|
-
color: sanitizeXmlColor(p.color as string,
|
|
158
|
+
color: sanitizeXmlColor(p.color as string, "4f46e5"),
|
|
170
159
|
underline: { type: docx.UnderlineType.SINGLE },
|
|
171
160
|
}),
|
|
172
161
|
],
|
|
@@ -189,9 +178,9 @@ function renderImage(ctx: DocxCtx, n: DocNode): void {
|
|
|
189
178
|
new docx.Paragraph({
|
|
190
179
|
children: [
|
|
191
180
|
new docx.ImageRun({
|
|
192
|
-
data: Buffer.from(parsed.data,
|
|
181
|
+
data: Buffer.from(parsed.data, "base64"),
|
|
193
182
|
transformation: { width: imgWidth, height: imgHeight },
|
|
194
|
-
type: parsed.mime ===
|
|
183
|
+
type: parsed.mime === "image/png" ? "png" : "jpg",
|
|
195
184
|
}),
|
|
196
185
|
],
|
|
197
186
|
alignment: alignmentMap(p.align as string) as any,
|
|
@@ -205,7 +194,7 @@ function renderImage(ctx: DocxCtx, n: DocNode): void {
|
|
|
205
194
|
text: p.caption as string,
|
|
206
195
|
italics: true,
|
|
207
196
|
size: 20,
|
|
208
|
-
color:
|
|
197
|
+
color: "666666",
|
|
209
198
|
}),
|
|
210
199
|
],
|
|
211
200
|
alignment: alignmentMap(p.align as string) as any,
|
|
@@ -214,15 +203,15 @@ function renderImage(ctx: DocxCtx, n: DocNode): void {
|
|
|
214
203
|
)
|
|
215
204
|
}
|
|
216
205
|
} else {
|
|
217
|
-
const alt = (p.alt as string) ??
|
|
218
|
-
const caption = p.caption ? ` — ${p.caption}` :
|
|
206
|
+
const alt = (p.alt as string) ?? "Image"
|
|
207
|
+
const caption = p.caption ? ` — ${p.caption}` : ""
|
|
219
208
|
children.push(
|
|
220
209
|
new docx.Paragraph({
|
|
221
210
|
children: [
|
|
222
211
|
new docx.TextRun({
|
|
223
212
|
text: `[${alt}${caption}]`,
|
|
224
213
|
italics: true,
|
|
225
|
-
color:
|
|
214
|
+
color: "999999",
|
|
226
215
|
}),
|
|
227
216
|
],
|
|
228
217
|
}),
|
|
@@ -233,16 +222,12 @@ function renderImage(ctx: DocxCtx, n: DocNode): void {
|
|
|
233
222
|
function renderDocxTable(ctx: DocxCtx, n: DocNode): void {
|
|
234
223
|
const { docx, children, alignmentMap } = ctx
|
|
235
224
|
const p = n.props
|
|
236
|
-
const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(
|
|
237
|
-
resolveColumn,
|
|
238
|
-
)
|
|
225
|
+
const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(resolveColumn)
|
|
239
226
|
const rows = (p.rows ?? []) as (string | number)[][]
|
|
240
|
-
const hs = p.headerStyle as
|
|
241
|
-
| { background?: string; color?: string }
|
|
242
|
-
| undefined
|
|
227
|
+
const hs = p.headerStyle as { background?: string; color?: string } | undefined
|
|
243
228
|
const bordered = p.bordered as boolean | undefined
|
|
244
229
|
const borderStyle = bordered
|
|
245
|
-
? { style: docx.BorderStyle.SINGLE, size: 1, color:
|
|
230
|
+
? { style: docx.BorderStyle.SINGLE, size: 1, color: "DDDDDD" }
|
|
246
231
|
: undefined
|
|
247
232
|
const cellBorders = borderStyle
|
|
248
233
|
? {
|
|
@@ -292,14 +277,12 @@ function renderDocxTable(ctx: DocxCtx, n: DocNode): void {
|
|
|
292
277
|
new docx.TableCell({
|
|
293
278
|
children: [
|
|
294
279
|
new docx.Paragraph({
|
|
295
|
-
children: [
|
|
296
|
-
new docx.TextRun({ text: String(row[colIdx] ?? '') }),
|
|
297
|
-
],
|
|
280
|
+
children: [new docx.TextRun({ text: String(row[colIdx] ?? "") })],
|
|
298
281
|
alignment: alignmentMap(col.align) as any,
|
|
299
282
|
}),
|
|
300
283
|
],
|
|
301
284
|
...(p.striped && rowIdx % 2 === 1
|
|
302
|
-
? { shading: { fill:
|
|
285
|
+
? { shading: { fill: "F9F9F9", type: docx.ShadingType.SOLID } }
|
|
303
286
|
: {}),
|
|
304
287
|
...(cellBorders != null ? { borders: cellBorders } : {}),
|
|
305
288
|
width: getColumnWidth(col.width as string | undefined) as any,
|
|
@@ -329,7 +312,7 @@ function renderDocxTable(ctx: DocxCtx, n: DocNode): void {
|
|
|
329
312
|
width: { size: 100, type: docx.WidthType.PERCENTAGE },
|
|
330
313
|
}),
|
|
331
314
|
)
|
|
332
|
-
children.push(new docx.Paragraph({ text:
|
|
315
|
+
children.push(new docx.Paragraph({ text: "", spacing: { after: 120 } }))
|
|
333
316
|
}
|
|
334
317
|
|
|
335
318
|
function renderList(ctx: DocxCtx, n: DocNode): void {
|
|
@@ -337,14 +320,14 @@ function renderList(ctx: DocxCtx, n: DocNode): void {
|
|
|
337
320
|
const ordered = n.props.ordered as boolean | undefined
|
|
338
321
|
const listRef = nextListId()
|
|
339
322
|
processListItems(n, listRef, 0, ordered ?? false)
|
|
340
|
-
children.push(new docx.Paragraph({ text:
|
|
323
|
+
children.push(new docx.Paragraph({ text: "", spacing: { after: 60 } }))
|
|
341
324
|
}
|
|
342
325
|
|
|
343
326
|
function renderButtonOrQuote(ctx: DocxCtx, n: DocNode): void {
|
|
344
327
|
const { docx, children } = ctx
|
|
345
328
|
const p = n.props
|
|
346
329
|
const text = getTextContent(n.children)
|
|
347
|
-
if (n.type ===
|
|
330
|
+
if (n.type === "button") {
|
|
348
331
|
children.push(
|
|
349
332
|
new docx.Paragraph({
|
|
350
333
|
children: [
|
|
@@ -354,7 +337,7 @@ function renderButtonOrQuote(ctx: DocxCtx, n: DocNode): void {
|
|
|
354
337
|
new docx.TextRun({
|
|
355
338
|
text,
|
|
356
339
|
bold: true,
|
|
357
|
-
color:
|
|
340
|
+
color: "4F46E5",
|
|
358
341
|
underline: { type: docx.UnderlineType.SINGLE },
|
|
359
342
|
}),
|
|
360
343
|
],
|
|
@@ -366,13 +349,13 @@ function renderButtonOrQuote(ctx: DocxCtx, n: DocNode): void {
|
|
|
366
349
|
} else {
|
|
367
350
|
children.push(
|
|
368
351
|
new docx.Paragraph({
|
|
369
|
-
children: [new docx.TextRun({ text, italics: true, color:
|
|
352
|
+
children: [new docx.TextRun({ text, italics: true, color: "555555" })],
|
|
370
353
|
indent: { left: 720 },
|
|
371
354
|
border: {
|
|
372
355
|
left: {
|
|
373
356
|
style: docx.BorderStyle.SINGLE,
|
|
374
357
|
size: 6,
|
|
375
|
-
color: sanitizeXmlColor(p.borderColor as string,
|
|
358
|
+
color: sanitizeXmlColor(p.borderColor as string, "DDDDDD"),
|
|
376
359
|
},
|
|
377
360
|
},
|
|
378
361
|
spacing: { after: 120 },
|
|
@@ -383,7 +366,14 @@ function renderButtonOrQuote(ctx: DocxCtx, n: DocNode): void {
|
|
|
383
366
|
|
|
384
367
|
export const docxRenderer: DocumentRenderer = {
|
|
385
368
|
async render(node: DocNode, _options?: RenderOptions): Promise<Uint8Array> {
|
|
386
|
-
|
|
369
|
+
let docx: typeof import("docx")
|
|
370
|
+
try {
|
|
371
|
+
docx = await import("docx")
|
|
372
|
+
} catch {
|
|
373
|
+
throw new Error(
|
|
374
|
+
'[@pyreon/document] DOCX renderer requires "docx" package. Install it: bun add docx',
|
|
375
|
+
)
|
|
376
|
+
}
|
|
387
377
|
const children: unknown[] = []
|
|
388
378
|
let listCounter = 0
|
|
389
379
|
|
|
@@ -398,43 +388,24 @@ export const docxRenderer: DocumentRenderer = {
|
|
|
398
388
|
return map[align]
|
|
399
389
|
}
|
|
400
390
|
|
|
401
|
-
function processListItems(
|
|
402
|
-
n: DocNode
|
|
403
|
-
listRef: string,
|
|
404
|
-
level: number,
|
|
405
|
-
ordered: boolean,
|
|
406
|
-
): void {
|
|
407
|
-
const items = n.children.filter(
|
|
408
|
-
(c): c is DocNode => typeof c !== 'string',
|
|
409
|
-
)
|
|
391
|
+
function processListItems(n: DocNode, listRef: string, level: number, ordered: boolean): void {
|
|
392
|
+
const items = n.children.filter((c): c is DocNode => typeof c !== "string")
|
|
410
393
|
for (const item of items) {
|
|
411
394
|
const nestedList = item.children.find(
|
|
412
|
-
(c): c is DocNode =>
|
|
413
|
-
typeof c !== 'string' && (c as DocNode).type === 'list',
|
|
395
|
+
(c): c is DocNode => typeof c !== "string" && (c as DocNode).type === "list",
|
|
414
396
|
)
|
|
415
397
|
const textChildren = item.children.filter(
|
|
416
|
-
(c) => typeof c ===
|
|
398
|
+
(c) => typeof c === "string" || (c as DocNode).type !== "list",
|
|
417
399
|
)
|
|
418
400
|
children.push(
|
|
419
401
|
new docx.Paragraph({
|
|
420
|
-
children: [
|
|
421
|
-
|
|
422
|
-
],
|
|
423
|
-
...(ordered
|
|
424
|
-
? { numbering: { reference: listRef, level } }
|
|
425
|
-
: { bullet: { level } }),
|
|
402
|
+
children: [new docx.TextRun({ text: getTextContent(textChildren) })],
|
|
403
|
+
...(ordered ? { numbering: { reference: listRef, level } } : { bullet: { level } }),
|
|
426
404
|
}),
|
|
427
405
|
)
|
|
428
406
|
if (nestedList) {
|
|
429
|
-
const nestedOrdered = (nestedList as DocNode).props.ordered as
|
|
430
|
-
|
|
431
|
-
| undefined
|
|
432
|
-
processListItems(
|
|
433
|
-
nestedList as DocNode,
|
|
434
|
-
listRef,
|
|
435
|
-
level + 1,
|
|
436
|
-
nestedOrdered ?? false,
|
|
437
|
-
)
|
|
407
|
+
const nestedOrdered = (nestedList as DocNode).props.ordered as boolean | undefined
|
|
408
|
+
processListItems(nestedList as DocNode, listRef, level + 1, nestedOrdered ?? false)
|
|
438
409
|
}
|
|
439
410
|
}
|
|
440
411
|
}
|
|
@@ -449,73 +420,73 @@ export const docxRenderer: DocumentRenderer = {
|
|
|
449
420
|
|
|
450
421
|
function processNode(n: DocNode): void {
|
|
451
422
|
switch (n.type) {
|
|
452
|
-
case
|
|
453
|
-
case
|
|
454
|
-
case
|
|
455
|
-
case
|
|
456
|
-
case
|
|
423
|
+
case "document":
|
|
424
|
+
case "page":
|
|
425
|
+
case "section":
|
|
426
|
+
case "row":
|
|
427
|
+
case "column":
|
|
457
428
|
for (const child of n.children) {
|
|
458
|
-
if (typeof child !==
|
|
429
|
+
if (typeof child !== "string") processNode(child)
|
|
459
430
|
else children.push(new docx.Paragraph({ text: child }))
|
|
460
431
|
}
|
|
461
432
|
break
|
|
462
|
-
case
|
|
433
|
+
case "heading":
|
|
463
434
|
renderHeading(ctx, n)
|
|
464
435
|
break
|
|
465
|
-
case
|
|
436
|
+
case "text":
|
|
466
437
|
renderTextNode(ctx, n)
|
|
467
438
|
break
|
|
468
|
-
case
|
|
439
|
+
case "link":
|
|
469
440
|
renderLink(ctx, n)
|
|
470
441
|
break
|
|
471
|
-
case
|
|
442
|
+
case "image":
|
|
472
443
|
renderImage(ctx, n)
|
|
473
444
|
break
|
|
474
|
-
case
|
|
445
|
+
case "table":
|
|
475
446
|
renderDocxTable(ctx, n)
|
|
476
447
|
break
|
|
477
|
-
case
|
|
448
|
+
case "list":
|
|
478
449
|
renderList(ctx, n)
|
|
479
450
|
break
|
|
480
|
-
case
|
|
451
|
+
case "code":
|
|
481
452
|
children.push(
|
|
482
453
|
new docx.Paragraph({
|
|
483
454
|
children: [
|
|
484
455
|
new docx.TextRun({
|
|
485
456
|
text: getTextContent(n.children),
|
|
486
|
-
font:
|
|
457
|
+
font: "Courier New",
|
|
487
458
|
size: 20,
|
|
488
459
|
}),
|
|
489
460
|
],
|
|
490
|
-
shading: { fill:
|
|
461
|
+
shading: { fill: "F5F5F5", type: docx.ShadingType.SOLID },
|
|
491
462
|
spacing: { after: 120 },
|
|
492
463
|
}),
|
|
493
464
|
)
|
|
494
465
|
break
|
|
495
|
-
case
|
|
466
|
+
case "divider":
|
|
496
467
|
children.push(
|
|
497
468
|
new docx.Paragraph({
|
|
498
469
|
border: {
|
|
499
470
|
bottom: {
|
|
500
471
|
style: docx.BorderStyle.SINGLE,
|
|
501
472
|
size: (n.props.thickness as number | undefined) ?? 1,
|
|
502
|
-
color: sanitizeXmlColor(n.props.color as string,
|
|
473
|
+
color: sanitizeXmlColor(n.props.color as string, "DDDDDD"),
|
|
503
474
|
},
|
|
504
475
|
},
|
|
505
476
|
spacing: { before: 120, after: 120 },
|
|
506
477
|
}),
|
|
507
478
|
)
|
|
508
479
|
break
|
|
509
|
-
case
|
|
480
|
+
case "spacer":
|
|
510
481
|
children.push(
|
|
511
482
|
new docx.Paragraph({
|
|
512
|
-
text:
|
|
483
|
+
text: "",
|
|
513
484
|
spacing: { after: (n.props.height as number) * 20 },
|
|
514
485
|
}),
|
|
515
486
|
)
|
|
516
487
|
break
|
|
517
|
-
case
|
|
518
|
-
case
|
|
488
|
+
case "button":
|
|
489
|
+
case "quote":
|
|
519
490
|
renderButtonOrQuote(ctx, n)
|
|
520
491
|
break
|
|
521
492
|
}
|
|
@@ -542,12 +513,11 @@ export const docxRenderer: DocumentRenderer = {
|
|
|
542
513
|
|
|
543
514
|
// Extract page properties from first page node
|
|
544
515
|
const pageNode =
|
|
545
|
-
node.type ===
|
|
516
|
+
node.type === "document"
|
|
546
517
|
? (node.children.find(
|
|
547
|
-
(c): c is DocNode =>
|
|
548
|
-
typeof c !== 'string' && (c as DocNode).type === 'page',
|
|
518
|
+
(c): c is DocNode => typeof c !== "string" && (c as DocNode).type === "page",
|
|
549
519
|
) as DocNode | undefined)
|
|
550
|
-
: node.type ===
|
|
520
|
+
: node.type === "page"
|
|
551
521
|
? node
|
|
552
522
|
: undefined
|
|
553
523
|
|
|
@@ -557,33 +527,23 @@ export const docxRenderer: DocumentRenderer = {
|
|
|
557
527
|
pageProps.orientation as PageOrientation | undefined,
|
|
558
528
|
)
|
|
559
529
|
const pageMargins = getPageMargins(
|
|
560
|
-
pageProps.margin as
|
|
561
|
-
| number
|
|
562
|
-
| [number, number]
|
|
563
|
-
| [number, number, number, number]
|
|
564
|
-
| undefined,
|
|
530
|
+
pageProps.margin as number | [number, number] | [number, number, number, number] | undefined,
|
|
565
531
|
)
|
|
566
532
|
|
|
567
|
-
function buildHeaderFooter(
|
|
568
|
-
contentNode: DocNode | undefined,
|
|
569
|
-
): unknown[] | undefined {
|
|
533
|
+
function buildHeaderFooter(contentNode: DocNode | undefined): unknown[] | undefined {
|
|
570
534
|
if (!contentNode) return undefined
|
|
571
535
|
const text = getTextContent(contentNode.children)
|
|
572
536
|
if (!text) return undefined
|
|
573
537
|
return [
|
|
574
538
|
new docx.Paragraph({
|
|
575
|
-
children: [new docx.TextRun({ text, size: 18, color:
|
|
539
|
+
children: [new docx.TextRun({ text, size: 18, color: "999999" })],
|
|
576
540
|
alignment: docx.AlignmentType.CENTER,
|
|
577
541
|
}),
|
|
578
542
|
]
|
|
579
543
|
}
|
|
580
544
|
|
|
581
|
-
const headerContent = buildHeaderFooter(
|
|
582
|
-
|
|
583
|
-
)
|
|
584
|
-
const footerContent = buildHeaderFooter(
|
|
585
|
-
pageProps.footer as DocNode | undefined,
|
|
586
|
-
)
|
|
545
|
+
const headerContent = buildHeaderFooter(pageProps.header as DocNode | undefined)
|
|
546
|
+
const footerContent = buildHeaderFooter(pageProps.footer as DocNode | undefined)
|
|
587
547
|
|
|
588
548
|
const sectionProperties: Record<string, unknown> = {}
|
|
589
549
|
if (pageDims) {
|
|
@@ -593,9 +553,7 @@ export const docxRenderer: DocumentRenderer = {
|
|
|
593
553
|
}
|
|
594
554
|
|
|
595
555
|
const doc = new docx.Document({
|
|
596
|
-
numbering: (numberingConfigs.length > 0
|
|
597
|
-
? { config: numberingConfigs }
|
|
598
|
-
: undefined) as any,
|
|
556
|
+
numbering: (numberingConfigs.length > 0 ? { config: numberingConfigs } : undefined) as any,
|
|
599
557
|
sections: [
|
|
600
558
|
{
|
|
601
559
|
properties: sectionProperties,
|