@pyreon/document 0.11.5 → 0.11.6

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.
Files changed (50) hide show
  1. package/README.md +7 -4
  2. package/lib/confluence-Bd3ua1Ut.js.map +1 -1
  3. package/lib/csv-COrS4qdy.js.map +1 -1
  4. package/lib/discord-BLUnkEh9.js.map +1 -1
  5. package/lib/docx-uNAel545.js.map +1 -1
  6. package/lib/email-D0bbfWq4.js.map +1 -1
  7. package/lib/google-chat-CkKCBUWC.js.map +1 -1
  8. package/lib/html-B5biprN2.js.map +1 -1
  9. package/lib/index.js.map +1 -1
  10. package/lib/markdown-CdtlFGC0.js.map +1 -1
  11. package/lib/notion-iG2C5bEY.js.map +1 -1
  12. package/lib/pdf-IuBgTb3T.js.map +1 -1
  13. package/lib/pptx-DXiMiYFM.js.map +1 -1
  14. package/lib/sanitize-O_3j1mNJ.js.map +1 -1
  15. package/lib/slack-BI3EQwYm.js.map +1 -1
  16. package/lib/svg-BKxumy-p.js.map +1 -1
  17. package/lib/teams-Cwz9lce0.js.map +1 -1
  18. package/lib/telegram-gYFqyMXb.js.map +1 -1
  19. package/lib/text-l1XNXBOC.js.map +1 -1
  20. package/lib/types/index.d.ts +27 -27
  21. package/lib/whatsapp-CjSGoOKx.js.map +1 -1
  22. package/lib/xlsx-Cvu4LBNy.js.map +1 -1
  23. package/package.json +21 -21
  24. package/src/builder.ts +36 -36
  25. package/src/download.ts +32 -32
  26. package/src/index.ts +5 -10
  27. package/src/nodes.ts +45 -45
  28. package/src/render.ts +43 -43
  29. package/src/renderers/confluence.ts +63 -63
  30. package/src/renderers/csv.ts +10 -10
  31. package/src/renderers/discord.ts +37 -37
  32. package/src/renderers/docx.ts +57 -57
  33. package/src/renderers/email.ts +72 -72
  34. package/src/renderers/google-chat.ts +34 -34
  35. package/src/renderers/html.ts +76 -76
  36. package/src/renderers/markdown.ts +42 -42
  37. package/src/renderers/notion.ts +60 -60
  38. package/src/renderers/pdf.ts +78 -78
  39. package/src/renderers/pptx.ts +51 -51
  40. package/src/renderers/slack.ts +48 -48
  41. package/src/renderers/svg.ts +47 -47
  42. package/src/renderers/teams.ts +67 -67
  43. package/src/renderers/telegram.ts +39 -39
  44. package/src/renderers/text.ts +43 -43
  45. package/src/renderers/whatsapp.ts +33 -33
  46. package/src/renderers/xlsx.ts +35 -35
  47. package/src/sanitize.ts +20 -20
  48. package/src/tests/document.test.ts +1302 -1302
  49. package/src/tests/stress.test.ts +110 -110
  50. package/src/types.ts +61 -61
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from "vitest"
1
+ import { describe, expect, it } from 'vitest'
2
2
  import {
3
3
  Document,
4
4
  Heading,
@@ -12,8 +12,8 @@ import {
12
12
  Spacer,
13
13
  Table,
14
14
  Text,
15
- } from "../index"
16
- import type { DocNode } from "../types"
15
+ } from '../index'
16
+ import type { DocNode } from '../types'
17
17
 
18
18
  // ─── Helpers ────────────────────────────────────────────────────────────────
19
19
 
@@ -34,10 +34,10 @@ function generateLargeDocument(pages: number, rowsPerTable: number): DocNode {
34
34
  children: `This is page ${p + 1} of the stress test document.`,
35
35
  }),
36
36
  Table({
37
- columns: ["ID", "Name", "Value", "Status", "Notes"],
37
+ columns: ['ID', 'Name', 'Value', 'Status', 'Notes'],
38
38
  rows: generateRows(rowsPerTable, 5),
39
39
  striped: true,
40
- headerStyle: { background: "#1a1a2e", color: "#fff" },
40
+ headerStyle: { background: '#1a1a2e', color: '#fff' },
41
41
  }),
42
42
  Spacer({ height: 20 }),
43
43
  List({
@@ -54,138 +54,138 @@ function generateLargeDocument(pages: number, rowsPerTable: number): DocNode {
54
54
  }
55
55
 
56
56
  return Document({
57
- title: "Stress Test Document",
58
- author: "Pyreon Test Suite",
57
+ title: 'Stress Test Document',
58
+ author: 'Pyreon Test Suite',
59
59
  children: pageNodes,
60
60
  })
61
61
  }
62
62
 
63
63
  // ─── HTML Stress Tests ──────────────────────────────────────────────────────
64
64
 
65
- describe("HTML stress tests", () => {
66
- it("renders 50-page document", async () => {
65
+ describe('HTML stress tests', () => {
66
+ it('renders 50-page document', async () => {
67
67
  const doc = generateLargeDocument(50, 20)
68
- const html = (await render(doc, "html")) as string
68
+ const html = (await render(doc, 'html')) as string
69
69
  expect(html.length).toBeGreaterThan(100000)
70
- expect(html).toContain("Page 1")
71
- expect(html).toContain("Page 50")
72
- expect(html).toContain("Row 20 Col 5")
70
+ expect(html).toContain('Page 1')
71
+ expect(html).toContain('Page 50')
72
+ expect(html).toContain('Row 20 Col 5')
73
73
  })
74
74
 
75
- it("renders 1000-row table", async () => {
75
+ it('renders 1000-row table', async () => {
76
76
  const doc = Document({
77
77
  children: Table({
78
- columns: ["A", "B", "C", "D", "E", "F", "G", "H"],
78
+ columns: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'],
79
79
  rows: generateRows(1000, 8),
80
80
  striped: true,
81
81
  bordered: true,
82
82
  }),
83
83
  })
84
- const html = (await render(doc, "html")) as string
85
- expect(html).toContain("Row 1 Col 1")
86
- expect(html).toContain("Row 1000 Col 8")
84
+ const html = (await render(doc, 'html')) as string
85
+ expect(html).toContain('Row 1 Col 1')
86
+ expect(html).toContain('Row 1000 Col 8')
87
87
  })
88
88
 
89
- it("renders deeply nested sections", async () => {
90
- let node: DocNode = Text({ children: "Deep content" })
89
+ it('renders deeply nested sections', async () => {
90
+ let node: DocNode = Text({ children: 'Deep content' })
91
91
  for (let i = 0; i < 20; i++) {
92
92
  node = Section({ children: node })
93
93
  }
94
94
  const doc = Document({ children: node })
95
- const html = (await render(doc, "html")) as string
96
- expect(html).toContain("Deep content")
95
+ const html = (await render(doc, 'html')) as string
96
+ expect(html).toContain('Deep content')
97
97
  })
98
98
  })
99
99
 
100
100
  // ─── Email Stress Tests ─────────────────────────────────────────────────────
101
101
 
102
- describe("email stress tests", () => {
103
- it("renders large email with multiple sections", async () => {
102
+ describe('email stress tests', () => {
103
+ it('renders large email with multiple sections', async () => {
104
104
  const doc = generateLargeDocument(5, 50)
105
- const html = (await render(doc, "email")) as string
106
- expect(html).toContain("max-width:600px")
107
- expect(html).toContain("Page 5")
108
- expect(html).toContain("Row 50 Col 5")
105
+ const html = (await render(doc, 'email')) as string
106
+ expect(html).toContain('max-width:600px')
107
+ expect(html).toContain('Page 5')
108
+ expect(html).toContain('Row 50 Col 5')
109
109
  })
110
110
  })
111
111
 
112
112
  // ─── Markdown Stress Tests ──────────────────────────────────────────────────
113
113
 
114
- describe("Markdown stress tests", () => {
115
- it("renders 1000-row table as pipe table", async () => {
114
+ describe('Markdown stress tests', () => {
115
+ it('renders 1000-row table as pipe table', async () => {
116
116
  const doc = Document({
117
117
  children: Table({
118
- columns: ["Name", "Value"],
118
+ columns: ['Name', 'Value'],
119
119
  rows: generateRows(1000, 2),
120
120
  }),
121
121
  })
122
- const md = (await render(doc, "md")) as string
123
- expect(md).toContain("Row 1 Col 1")
124
- expect(md).toContain("Row 1000 Col 2")
122
+ const md = (await render(doc, 'md')) as string
123
+ expect(md).toContain('Row 1 Col 1')
124
+ expect(md).toContain('Row 1000 Col 2')
125
125
  // Count pipe rows
126
- const pipeLines = md.split("\n").filter((l) => l.startsWith("|"))
126
+ const pipeLines = md.split('\n').filter((l) => l.startsWith('|'))
127
127
  expect(pipeLines.length).toBeGreaterThanOrEqual(1002) // header + separator + 1000 rows
128
128
  })
129
129
  })
130
130
 
131
131
  // ─── CSV Stress Tests ───────────────────────────────────────────────────────
132
132
 
133
- describe("CSV stress tests", () => {
134
- it("renders multiple large tables", async () => {
133
+ describe('CSV stress tests', () => {
134
+ it('renders multiple large tables', async () => {
135
135
  const doc = Document({
136
136
  children: [
137
137
  Table({
138
- columns: ["A", "B", "C"],
138
+ columns: ['A', 'B', 'C'],
139
139
  rows: generateRows(500, 3),
140
- caption: "Table 1",
140
+ caption: 'Table 1',
141
141
  }),
142
142
  Table({
143
- columns: ["X", "Y", "Z"],
143
+ columns: ['X', 'Y', 'Z'],
144
144
  rows: generateRows(500, 3),
145
- caption: "Table 2",
145
+ caption: 'Table 2',
146
146
  }),
147
147
  ],
148
148
  })
149
- const csv = (await render(doc, "csv")) as string
150
- expect(csv).toContain("# Table 1")
151
- expect(csv).toContain("# Table 2")
152
- const lines = csv.split("\n").filter((l) => l.trim().length > 0)
149
+ const csv = (await render(doc, 'csv')) as string
150
+ expect(csv).toContain('# Table 1')
151
+ expect(csv).toContain('# Table 2')
152
+ const lines = csv.split('\n').filter((l) => l.trim().length > 0)
153
153
  expect(lines.length).toBeGreaterThanOrEqual(1004) // 2 tables × (header + 500 rows) + 2 captions
154
154
  })
155
155
  })
156
156
 
157
157
  // ─── Text Stress Tests ──────────────────────────────────────────────────────
158
158
 
159
- describe("text stress tests", () => {
160
- it("renders large aligned table", async () => {
159
+ describe('text stress tests', () => {
160
+ it('renders large aligned table', async () => {
161
161
  const doc = Document({
162
162
  children: Table({
163
163
  columns: [
164
- { header: "ID", align: "right" as const },
165
- { header: "Name", align: "left" as const },
166
- { header: "Amount", align: "right" as const },
164
+ { header: 'ID', align: 'right' as const },
165
+ { header: 'Name', align: 'left' as const },
166
+ { header: 'Amount', align: 'right' as const },
167
167
  ],
168
168
  rows: generateRows(200, 3),
169
169
  }),
170
170
  })
171
- const text = (await render(doc, "text")) as string
172
- expect(text).toContain("Row 200 Col 3")
171
+ const text = (await render(doc, 'text')) as string
172
+ expect(text).toContain('Row 200 Col 3')
173
173
  })
174
174
  })
175
175
 
176
176
  // ─── SVG Stress Tests ───────────────────────────────────────────────────────
177
177
 
178
- describe("SVG stress tests", () => {
179
- it("renders document with many elements", async () => {
178
+ describe('SVG stress tests', () => {
179
+ it('renders document with many elements', async () => {
180
180
  const children: DocNode[] = []
181
181
  for (let i = 0; i < 100; i++) {
182
182
  children.push(Heading({ level: 2, children: `Section ${i + 1}` }))
183
183
  children.push(Text({ children: `Content for section ${i + 1}` }))
184
184
  }
185
185
  const doc = Document({ children })
186
- const svg = (await render(doc, "svg")) as string
187
- expect(svg).toContain("<svg")
188
- expect(svg).toContain("Section 100")
186
+ const svg = (await render(doc, 'svg')) as string
187
+ expect(svg).toContain('<svg')
188
+ expect(svg).toContain('Section 100')
189
189
  // Height should be large
190
190
  const match = svg.match(/height="(\d+)"/)
191
191
  expect(Number(match?.[1])).toBeGreaterThan(3000)
@@ -194,10 +194,10 @@ describe("SVG stress tests", () => {
194
194
 
195
195
  // ─── Slack Stress Tests ─────────────────────────────────────────────────────
196
196
 
197
- describe("Slack stress tests", () => {
198
- it("renders large document to blocks", async () => {
197
+ describe('Slack stress tests', () => {
198
+ it('renders large document to blocks', async () => {
199
199
  const doc = generateLargeDocument(10, 10)
200
- const json = (await render(doc, "slack")) as string
200
+ const json = (await render(doc, 'slack')) as string
201
201
  const parsed = JSON.parse(json)
202
202
  expect(parsed.blocks.length).toBeGreaterThan(50)
203
203
  })
@@ -205,29 +205,29 @@ describe("Slack stress tests", () => {
205
205
 
206
206
  // ─── PDF Stress Tests ───────────────────────────────────────────────────────
207
207
 
208
- describe("PDF stress tests", () => {
209
- it("renders 10-page document with large tables", async () => {
208
+ describe('PDF stress tests', () => {
209
+ it('renders 10-page document with large tables', async () => {
210
210
  const doc = generateLargeDocument(10, 50)
211
- const pdf = await render(doc, "pdf")
211
+ const pdf = await render(doc, 'pdf')
212
212
  expect(pdf).toBeInstanceOf(Uint8Array)
213
213
  expect((pdf as Uint8Array).length).toBeGreaterThan(10000)
214
214
  // PDF header
215
215
  const header = String.fromCharCode(...(pdf as Uint8Array).slice(0, 5))
216
- expect(header).toBe("%PDF-")
216
+ expect(header).toBe('%PDF-')
217
217
  }, 30000)
218
218
  })
219
219
 
220
220
  // ─── DOCX Stress Tests ──────────────────────────────────────────────────────
221
221
 
222
- describe("DOCX stress tests", () => {
223
- it("renders document with 500-row table", async () => {
222
+ describe('DOCX stress tests', () => {
223
+ it('renders document with 500-row table', async () => {
224
224
  const doc = Document({
225
- title: "Large DOCX",
225
+ title: 'Large DOCX',
226
226
  children: Page({
227
227
  children: [
228
- Heading({ children: "Large Table" }),
228
+ Heading({ children: 'Large Table' }),
229
229
  Table({
230
- columns: ["A", "B", "C", "D"],
230
+ columns: ['A', 'B', 'C', 'D'],
231
231
  rows: generateRows(500, 4),
232
232
  striped: true,
233
233
  bordered: true,
@@ -235,34 +235,34 @@ describe("DOCX stress tests", () => {
235
235
  ],
236
236
  }),
237
237
  })
238
- const docx = await render(doc, "docx")
238
+ const docx = await render(doc, 'docx')
239
239
  expect(docx).toBeInstanceOf(Uint8Array)
240
240
  expect((docx as Uint8Array).length).toBeGreaterThan(5000)
241
241
  // DOCX is a ZIP — starts with PK
242
242
  const header = String.fromCharCode(...(docx as Uint8Array).slice(0, 2))
243
- expect(header).toBe("PK")
243
+ expect(header).toBe('PK')
244
244
  }, 30000)
245
245
  })
246
246
 
247
247
  // ─── XLSX Stress Tests ──────────────────────────────────────────────────────
248
248
 
249
- describe("XLSX stress tests", () => {
250
- it("renders 1000-row spreadsheet", async () => {
249
+ describe('XLSX stress tests', () => {
250
+ it('renders 1000-row spreadsheet', async () => {
251
251
  const doc = Document({
252
- title: "Large XLSX",
252
+ title: 'Large XLSX',
253
253
  children: Table({
254
- columns: ["ID", "Name", "Revenue", "Growth", "Region"],
254
+ columns: ['ID', 'Name', 'Revenue', 'Growth', 'Region'],
255
255
  rows: Array.from({ length: 1000 }, (_, i) => [
256
256
  String(i + 1),
257
257
  `Company ${i + 1}`,
258
258
  `$${(Math.random() * 1000000).toFixed(0)}`,
259
259
  `${(Math.random() * 100).toFixed(1)}%`,
260
- ["US", "EU", "APAC", "LATAM"][i % 4]!,
260
+ ['US', 'EU', 'APAC', 'LATAM'][i % 4]!,
261
261
  ]),
262
262
  striped: true,
263
263
  }),
264
264
  })
265
- const xlsx = await render(doc, "xlsx")
265
+ const xlsx = await render(doc, 'xlsx')
266
266
  expect(xlsx).toBeInstanceOf(Uint8Array)
267
267
  expect((xlsx as Uint8Array).length).toBeGreaterThan(10000)
268
268
  }, 30000)
@@ -270,8 +270,8 @@ describe("XLSX stress tests", () => {
270
270
 
271
271
  // ─── PPTX Stress Tests ──────────────────────────────────────────────────────
272
272
 
273
- describe("PPTX stress tests", () => {
274
- it("renders 20-slide presentation", async () => {
273
+ describe('PPTX stress tests', () => {
274
+ it('renders 20-slide presentation', async () => {
275
275
  const pages: DocNode[] = []
276
276
  for (let i = 0; i < 20; i++) {
277
277
  pages.push(
@@ -280,18 +280,18 @@ describe("PPTX stress tests", () => {
280
280
  Heading({ children: `Slide ${i + 1}` }),
281
281
  Text({ children: `Content for slide ${i + 1}` }),
282
282
  Table({
283
- columns: ["Metric", "Value"],
283
+ columns: ['Metric', 'Value'],
284
284
  rows: [
285
- ["Revenue", `$${(i + 1) * 100}K`],
286
- ["Growth", `${(i + 1) * 5}%`],
285
+ ['Revenue', `$${(i + 1) * 100}K`],
286
+ ['Growth', `${(i + 1) * 5}%`],
287
287
  ],
288
288
  }),
289
289
  ],
290
290
  }),
291
291
  )
292
292
  }
293
- const doc = Document({ title: "Large Presentation", children: pages })
294
- const pptx = await render(doc, "pptx")
293
+ const doc = Document({ title: 'Large Presentation', children: pages })
294
+ const pptx = await render(doc, 'pptx')
295
295
  expect(pptx).toBeInstanceOf(Uint8Array)
296
296
  expect((pptx as Uint8Array).length).toBeGreaterThan(5000)
297
297
  }, 30000)
@@ -299,52 +299,52 @@ describe("PPTX stress tests", () => {
299
299
 
300
300
  // ─── Edge Cases ─────────────────────────────────────────────────────────────
301
301
 
302
- describe("edge cases", () => {
303
- it("handles empty document", async () => {
302
+ describe('edge cases', () => {
303
+ it('handles empty document', async () => {
304
304
  const doc = Document({ children: [] as unknown as undefined })
305
- const html = (await render(doc, "html")) as string
306
- expect(html).toContain("<!DOCTYPE html>")
305
+ const html = (await render(doc, 'html')) as string
306
+ expect(html).toContain('<!DOCTYPE html>')
307
307
  })
308
308
 
309
- it("handles empty table", async () => {
309
+ it('handles empty table', async () => {
310
310
  const doc = Document({
311
- children: Table({ columns: ["A", "B"], rows: [] }),
311
+ children: Table({ columns: ['A', 'B'], rows: [] }),
312
312
  })
313
- const html = (await render(doc, "html")) as string
314
- expect(html).toContain("<table")
313
+ const html = (await render(doc, 'html')) as string
314
+ expect(html).toContain('<table')
315
315
  })
316
316
 
317
- it("handles special characters in text", async () => {
317
+ it('handles special characters in text', async () => {
318
318
  const doc = Document({
319
319
  children: [
320
- Text({ children: "Hello <world> & \"quotes\" 'apostrophe'" }),
321
- Heading({ children: "Heading with <html>" }),
320
+ Text({ children: 'Hello <world> & "quotes" \'apostrophe\'' }),
321
+ Heading({ children: 'Heading with <html>' }),
322
322
  ],
323
323
  })
324
- const html = (await render(doc, "html")) as string
325
- expect(html).toContain("&lt;world&gt;")
326
- expect(html).toContain("&amp;")
327
- expect(html).toContain("&quot;")
324
+ const html = (await render(doc, 'html')) as string
325
+ expect(html).toContain('&lt;world&gt;')
326
+ expect(html).toContain('&amp;')
327
+ expect(html).toContain('&quot;')
328
328
  })
329
329
 
330
- it("handles unicode text", async () => {
330
+ it('handles unicode text', async () => {
331
331
  const doc = Document({
332
332
  children: [
333
- Text({ children: "日本語テスト" }),
334
- Text({ children: "العربية" }),
335
- Text({ children: "🎉🚀✨" }),
333
+ Text({ children: '日本語テスト' }),
334
+ Text({ children: 'العربية' }),
335
+ Text({ children: '🎉🚀✨' }),
336
336
  ],
337
337
  })
338
- const html = (await render(doc, "html")) as string
339
- expect(html).toContain("日本語テスト")
340
- expect(html).toContain("العربية")
341
- expect(html).toContain("🎉🚀✨")
338
+ const html = (await render(doc, 'html')) as string
339
+ expect(html).toContain('日本語テスト')
340
+ expect(html).toContain('العربية')
341
+ expect(html).toContain('🎉🚀✨')
342
342
  })
343
343
 
344
- it("handles very long text", async () => {
345
- const longText = "A".repeat(100000)
344
+ it('handles very long text', async () => {
345
+ const longText = 'A'.repeat(100000)
346
346
  const doc = Document({ children: Text({ children: longText }) })
347
- const html = (await render(doc, "html")) as string
347
+ const html = (await render(doc, 'html')) as string
348
348
  expect(html.length).toBeGreaterThan(100000)
349
349
  })
350
350
  })