@pyreon/document 0.9.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.
Files changed (76) hide show
  1. package/lib/analysis/index.js.html +1 -1
  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/{dist-BsqdI2nY.js → dist-CYL41kqQ.js} +2 -2
  6. package/lib/dist-CYL41kqQ.js.map +1 -0
  7. package/lib/{docx-BEBOihjl.js → docx-uNAel545.js} +7 -2
  8. package/lib/docx-uNAel545.js.map +1 -0
  9. package/lib/email-D0bbfWq4.js.map +1 -1
  10. package/lib/{exceljs-BoIDUUaw.js → exceljs-BYETsesT.js} +314 -314
  11. package/lib/exceljs-BYETsesT.js.map +1 -0
  12. package/lib/google-chat-CkKCBUWC.js.map +1 -1
  13. package/lib/html-B5biprN2.js.map +1 -1
  14. package/lib/index.js +17 -8
  15. package/lib/index.js.map +1 -1
  16. package/lib/markdown-CdtlFGC0.js.map +1 -1
  17. package/lib/notion-iG2C5bEY.js.map +1 -1
  18. package/lib/{pdf-DIUQUEdj.js → pdf-IuBgTb3T.js} +9 -3
  19. package/lib/pdf-IuBgTb3T.js.map +1 -0
  20. package/lib/{pdfmake-DnmLxK4Q.js → pdfmake-CKMX5URW.js} +2 -4
  21. package/lib/pdfmake-CKMX5URW.js.map +1 -0
  22. package/lib/{pptx-Dd33oL3_.js → pptx-DXiMiYFM.js} +7 -2
  23. package/lib/pptx-DXiMiYFM.js.map +1 -0
  24. package/lib/{pptxgen.es-COcgXsyx.js → pptxgen.es-FsqHs8mD.js} +3 -6
  25. package/lib/pptxgen.es-FsqHs8mD.js.map +1 -0
  26. package/lib/sanitize-O_3j1mNJ.js.map +1 -1
  27. package/lib/slack-BI3EQwYm.js.map +1 -1
  28. package/lib/svg-BKxumy-p.js.map +1 -1
  29. package/lib/teams-Cwz9lce0.js.map +1 -1
  30. package/lib/telegram-gYFqyMXb.js.map +1 -1
  31. package/lib/text-l1XNXBOC.js.map +1 -1
  32. package/lib/types/index.d.ts +43 -39
  33. package/lib/types/index.d.ts.map +1 -1
  34. package/lib/{vfs_fonts-Df1kkZ4Y.js → vfs_fonts-Cap07Jg3.js} +2 -2
  35. package/lib/vfs_fonts-Cap07Jg3.js.map +1 -0
  36. package/lib/whatsapp-CjSGoOKx.js.map +1 -1
  37. package/lib/{xlsx-Bb5TWyXQ.js → xlsx-Cvu4LBNy.js} +8 -2
  38. package/lib/xlsx-Cvu4LBNy.js.map +1 -0
  39. package/package.json +19 -7
  40. package/src/builder.ts +53 -44
  41. package/src/download.ts +32 -36
  42. package/src/env.d.ts +3 -17
  43. package/src/index.ts +6 -8
  44. package/src/nodes.ts +45 -45
  45. package/src/render.ts +45 -118
  46. package/src/renderers/confluence.ts +64 -80
  47. package/src/renderers/csv.ts +11 -18
  48. package/src/renderers/discord.ts +38 -50
  49. package/src/renderers/docx.ts +78 -120
  50. package/src/renderers/email.ts +73 -92
  51. package/src/renderers/google-chat.ts +35 -47
  52. package/src/renderers/html.ts +78 -101
  53. package/src/renderers/markdown.ts +43 -53
  54. package/src/renderers/notion.ts +63 -85
  55. package/src/renderers/pdf.ts +92 -115
  56. package/src/renderers/pptx.ts +60 -66
  57. package/src/renderers/slack.ts +49 -61
  58. package/src/renderers/svg.ts +49 -63
  59. package/src/renderers/teams.ts +68 -80
  60. package/src/renderers/telegram.ts +40 -54
  61. package/src/renderers/text.ts +44 -66
  62. package/src/renderers/whatsapp.ts +34 -48
  63. package/src/renderers/xlsx.ts +47 -61
  64. package/src/sanitize.ts +21 -25
  65. package/src/tests/document.test.ts +1337 -1385
  66. package/src/tests/stress.test.ts +350 -0
  67. package/src/types.ts +66 -65
  68. package/lib/dist-BsqdI2nY.js.map +0 -1
  69. package/lib/docx-BEBOihjl.js.map +0 -1
  70. package/lib/exceljs-BoIDUUaw.js.map +0 -1
  71. package/lib/pdf-DIUQUEdj.js.map +0 -1
  72. package/lib/pdfmake-DnmLxK4Q.js.map +0 -1
  73. package/lib/pptx-Dd33oL3_.js.map +0 -1
  74. package/lib/pptxgen.es-COcgXsyx.js.map +0 -1
  75. package/lib/vfs_fonts-Df1kkZ4Y.js.map +0 -1
  76. package/lib/xlsx-Bb5TWyXQ.js.map +0 -1
@@ -1,11 +1,5 @@
1
- import { sanitizeColor, sanitizeHref, sanitizeImageSrc } from '../sanitize'
2
- import type {
3
- DocChild,
4
- DocNode,
5
- DocumentRenderer,
6
- RenderOptions,
7
- TableColumn,
8
- } from '../types'
1
+ import { sanitizeColor, sanitizeHref, sanitizeImageSrc } from "../sanitize"
2
+ import type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } from "../types"
9
3
 
10
4
  /**
11
5
  * SVG renderer — generates a standalone SVG document from the node tree.
@@ -14,23 +8,21 @@ import type {
14
8
  */
15
9
 
16
10
  function resolveColumn(col: string | TableColumn): TableColumn {
17
- return typeof col === 'string' ? { header: col } : col
11
+ return typeof col === "string" ? { header: col } : col
18
12
  }
19
13
 
20
14
  function escapeXml(str: string): string {
21
15
  return str
22
- .replace(/&/g, '&')
23
- .replace(/</g, '&lt;')
24
- .replace(/>/g, '&gt;')
25
- .replace(/"/g, '&quot;')
16
+ .replace(/&/g, "&amp;")
17
+ .replace(/</g, "&lt;")
18
+ .replace(/>/g, "&gt;")
19
+ .replace(/"/g, "&quot;")
26
20
  }
27
21
 
28
22
  function getTextContent(children: DocChild[]): string {
29
23
  return children
30
- .map((c) =>
31
- typeof c === 'string' ? c : getTextContent((c as DocNode).children),
32
- )
33
- .join('')
24
+ .map((c) => (typeof c === "string" ? c : getTextContent((c as DocNode).children)))
25
+ .join("")
34
26
  }
35
27
 
36
28
  interface RenderContext {
@@ -42,22 +34,22 @@ interface RenderContext {
42
34
  function renderNode(node: DocNode, ctx: RenderContext): string {
43
35
  const p = node.props
44
36
  const contentWidth = ctx.width - ctx.padding * 2
45
- let svg = ''
37
+ let svg = ""
46
38
 
47
39
  switch (node.type) {
48
- case 'document':
49
- case 'page':
50
- case 'section':
51
- case 'row':
52
- case 'column':
40
+ case "document":
41
+ case "page":
42
+ case "section":
43
+ case "row":
44
+ case "column":
53
45
  for (const child of node.children) {
54
- if (typeof child !== 'string') {
46
+ if (typeof child !== "string") {
55
47
  svg += renderNode(child, ctx)
56
48
  }
57
49
  }
58
50
  break
59
51
 
60
- case 'heading': {
52
+ case "heading": {
61
53
  const level = (p.level as number) ?? 1
62
54
  const sizes: Record<number, number> = {
63
55
  1: 28,
@@ -68,7 +60,7 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
68
60
  6: 14,
69
61
  }
70
62
  const size = sizes[level] ?? 24
71
- const color = sanitizeColor((p.color as string) ?? '#000000')
63
+ const color = sanitizeColor((p.color as string) ?? "#000000")
72
64
  const text = escapeXml(getTextContent(node.children))
73
65
  ctx.y += size + 8
74
66
  svg += `<text x="${ctx.padding}" y="${ctx.y}" font-size="${size}" font-weight="bold" fill="${color}" font-family="system-ui, -apple-system, sans-serif">${text}</text>`
@@ -76,11 +68,11 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
76
68
  break
77
69
  }
78
70
 
79
- case 'text': {
71
+ case "text": {
80
72
  const size = (p.size as number) ?? 14
81
- const color = sanitizeColor((p.color as string) ?? '#333333')
82
- const weight = p.bold ? 'bold' : 'normal'
83
- const style = p.italic ? 'italic' : 'normal'
73
+ const color = sanitizeColor((p.color as string) ?? "#333333")
74
+ const weight = p.bold ? "bold" : "normal"
75
+ const style = p.italic ? "italic" : "normal"
84
76
  const text = escapeXml(getTextContent(node.children))
85
77
  ctx.y += size + 4
86
78
  svg += `<text x="${ctx.padding}" y="${ctx.y}" font-size="${size}" font-weight="${weight}" font-style="${style}" fill="${color}" font-family="system-ui, -apple-system, sans-serif">${text}</text>`
@@ -88,27 +80,27 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
88
80
  break
89
81
  }
90
82
 
91
- case 'link': {
83
+ case "link": {
92
84
  const href = sanitizeHref(p.href as string)
93
85
  const text = escapeXml(getTextContent(node.children))
94
- const color = sanitizeColor((p.color as string) ?? '#4f46e5')
86
+ const color = sanitizeColor((p.color as string) ?? "#4f46e5")
95
87
  ctx.y += 18
96
88
  svg += `<a href="${escapeXml(href)}"><text x="${ctx.padding}" y="${ctx.y}" font-size="14" fill="${color}" text-decoration="underline" font-family="system-ui, -apple-system, sans-serif">${text}</text></a>`
97
89
  ctx.y += 10
98
90
  break
99
91
  }
100
92
 
101
- case 'image': {
93
+ case "image": {
102
94
  const width = (p.width as number) ?? Math.min(contentWidth, 400)
103
95
  const height = (p.height as number) ?? 200
104
96
  const src = sanitizeImageSrc(p.src as string)
105
97
 
106
- if (src.startsWith('data:') || src.startsWith('http')) {
98
+ if (src.startsWith("data:") || src.startsWith("http")) {
107
99
  svg += `<image x="${ctx.padding}" y="${ctx.y}" width="${width}" height="${height}" href="${escapeXml(src)}" />`
108
100
  } else {
109
101
  // Placeholder rectangle for local paths
110
102
  svg += `<rect x="${ctx.padding}" y="${ctx.y}" width="${width}" height="${height}" fill="#f0f0f0" stroke="#ddd" rx="4" />`
111
- svg += `<text x="${ctx.padding + width / 2}" y="${ctx.y + height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999" font-family="system-ui, sans-serif">${escapeXml((p.alt as string) ?? 'Image')}</text>`
103
+ svg += `<text x="${ctx.padding + width / 2}" y="${ctx.y + height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999" font-family="system-ui, sans-serif">${escapeXml((p.alt as string) ?? "Image")}</text>`
112
104
  }
113
105
  ctx.y += height + 8
114
106
 
@@ -120,20 +112,16 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
120
112
  break
121
113
  }
122
114
 
123
- case 'table': {
124
- const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(
125
- resolveColumn,
126
- )
115
+ case "table": {
116
+ const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(resolveColumn)
127
117
  const rows = (p.rows ?? []) as (string | number)[][]
128
- const hs = p.headerStyle as
129
- | { background?: string; color?: string }
130
- | undefined
118
+ const hs = p.headerStyle as { background?: string; color?: string } | undefined
131
119
  const striped = p.striped as boolean | undefined
132
120
 
133
121
  const colWidth = contentWidth / columns.length
134
122
  const rowHeight = 28
135
- const headerBg = sanitizeColor(hs?.background ?? '#f5f5f5')
136
- const headerColor = sanitizeColor(hs?.color ?? '#000000')
123
+ const headerBg = sanitizeColor(hs?.background ?? "#f5f5f5")
124
+ const headerColor = sanitizeColor(hs?.color ?? "#000000")
137
125
 
138
126
  // Header
139
127
  svg += `<rect x="${ctx.padding}" y="${ctx.y}" width="${contentWidth}" height="${rowHeight}" fill="${headerBg}" />`
@@ -150,7 +138,7 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
150
138
  svg += `<rect x="${ctx.padding}" y="${ctx.y}" width="${contentWidth}" height="${rowHeight}" fill="#f9f9f9" />`
151
139
  }
152
140
  for (let c = 0; c < columns.length; c++) {
153
- svg += `<text x="${ctx.padding + c * colWidth + 8}" y="${ctx.y + 18}" font-size="12" fill="#333" font-family="system-ui, sans-serif">${escapeXml(String(rows[r]?.[c] ?? ''))}</text>`
141
+ svg += `<text x="${ctx.padding + c * colWidth + 8}" y="${ctx.y + 18}" font-size="12" fill="#333" font-family="system-ui, sans-serif">${escapeXml(String(rows[r]?.[c] ?? ""))}</text>`
154
142
  }
155
143
  ctx.y += rowHeight
156
144
  }
@@ -161,15 +149,13 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
161
149
  break
162
150
  }
163
151
 
164
- case 'list': {
152
+ case "list": {
165
153
  const ordered = p.ordered as boolean | undefined
166
- const items = node.children.filter(
167
- (c): c is DocNode => typeof c !== 'string',
168
- )
154
+ const items = node.children.filter((c): c is DocNode => typeof c !== "string")
169
155
  for (let i = 0; i < items.length; i++) {
170
156
  const item = items[i]
171
157
  if (!item) continue
172
- const prefix = ordered ? `${i + 1}.` : ''
158
+ const prefix = ordered ? `${i + 1}.` : ""
173
159
  const text = escapeXml(getTextContent(item.children))
174
160
  ctx.y += 18
175
161
  svg += `<text x="${ctx.padding + 16}" y="${ctx.y}" font-size="13" fill="#333" font-family="system-ui, sans-serif">${prefix} ${text}</text>`
@@ -178,20 +164,20 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
178
164
  break
179
165
  }
180
166
 
181
- case 'code': {
167
+ case "code": {
182
168
  const text = getTextContent(node.children)
183
- const lines = text.split('\n')
169
+ const lines = text.split("\n")
184
170
  const codeHeight = lines.length * 18 + 16
185
171
  svg += `<rect x="${ctx.padding}" y="${ctx.y}" width="${contentWidth}" height="${codeHeight}" fill="#f5f5f5" rx="4" />`
186
172
  for (let i = 0; i < lines.length; i++) {
187
- svg += `<text x="${ctx.padding + 12}" y="${ctx.y + 20 + i * 18}" font-size="12" fill="#333" font-family="monospace">${escapeXml(lines[i] ?? '')}</text>`
173
+ svg += `<text x="${ctx.padding + 12}" y="${ctx.y + 20 + i * 18}" font-size="12" fill="#333" font-family="monospace">${escapeXml(lines[i] ?? "")}</text>`
188
174
  }
189
175
  ctx.y += codeHeight + 8
190
176
  break
191
177
  }
192
178
 
193
- case 'divider': {
194
- const color = sanitizeColor((p.color as string) ?? '#ddd')
179
+ case "divider": {
180
+ const color = sanitizeColor((p.color as string) ?? "#ddd")
195
181
  const thickness = (p.thickness as number) ?? 1
196
182
  ctx.y += 12
197
183
  svg += `<line x1="${ctx.padding}" y1="${ctx.y}" x2="${ctx.padding + contentWidth}" y2="${ctx.y}" stroke="${color}" stroke-width="${thickness}" />`
@@ -199,19 +185,19 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
199
185
  break
200
186
  }
201
187
 
202
- case 'page-break':
188
+ case "page-break":
203
189
  ctx.y += 16
204
190
  svg += `<line x1="${ctx.padding}" y1="${ctx.y}" x2="${ctx.padding + contentWidth}" y2="${ctx.y}" stroke="#ccc" stroke-width="2" stroke-dasharray="8,4" />`
205
191
  ctx.y += 16
206
192
  break
207
193
 
208
- case 'spacer':
194
+ case "spacer":
209
195
  ctx.y += (p.height as number) ?? 12
210
196
  break
211
197
 
212
- case 'button': {
213
- const bg = sanitizeColor((p.background as string) ?? '#4f46e5')
214
- const color = sanitizeColor((p.color as string) ?? '#ffffff')
198
+ case "button": {
199
+ const bg = sanitizeColor((p.background as string) ?? "#4f46e5")
200
+ const color = sanitizeColor((p.color as string) ?? "#ffffff")
215
201
  const text = escapeXml(getTextContent(node.children))
216
202
  const btnWidth = Math.min(text.length * 10 + 48, contentWidth)
217
203
  const btnHeight = 40
@@ -222,8 +208,8 @@ function renderNode(node: DocNode, ctx: RenderContext): string {
222
208
  break
223
209
  }
224
210
 
225
- case 'quote': {
226
- const borderColor = sanitizeColor((p.borderColor as string) ?? '#ddd')
211
+ case "quote": {
212
+ const borderColor = sanitizeColor((p.borderColor as string) ?? "#ddd")
227
213
  const text = escapeXml(getTextContent(node.children))
228
214
  ctx.y += 4
229
215
  svg += `<rect x="${ctx.padding}" y="${ctx.y}" width="4" height="20" fill="${borderColor}" />`
@@ -245,7 +231,7 @@ export const svgRenderer: DocumentRenderer = {
245
231
  const content = renderNode(node, ctx)
246
232
  const height = ctx.y + padding
247
233
 
248
- const dir = options?.direction === 'rtl' ? ' direction="rtl"' : ''
234
+ const dir = options?.direction === "rtl" ? ' direction="rtl"' : ""
249
235
 
250
236
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}"${dir}>
251
237
  <rect width="${width}" height="${height}" fill="#ffffff" />
@@ -1,11 +1,5 @@
1
- import { sanitizeHref, sanitizeImageSrc } from '../sanitize'
2
- import type {
3
- DocChild,
4
- DocNode,
5
- DocumentRenderer,
6
- RenderOptions,
7
- TableColumn,
8
- } from '../types'
1
+ import { sanitizeHref, sanitizeImageSrc } from "../sanitize"
2
+ import type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } from "../types"
9
3
 
10
4
  /**
11
5
  * Microsoft Teams renderer — outputs Adaptive Cards JSON.
@@ -13,15 +7,13 @@ import type {
13
7
  */
14
8
 
15
9
  function resolveColumn(col: string | TableColumn): TableColumn {
16
- return typeof col === 'string' ? { header: col } : col
10
+ return typeof col === "string" ? { header: col } : col
17
11
  }
18
12
 
19
13
  function getTextContent(children: DocChild[]): string {
20
14
  return children
21
- .map((c) =>
22
- typeof c === 'string' ? c : getTextContent((c as DocNode).children),
23
- )
24
- .join('')
15
+ .map((c) => (typeof c === "string" ? c : getTextContent((c as DocNode).children)))
16
+ .join("")
25
17
  }
26
18
 
27
19
  interface AdaptiveElement {
@@ -34,99 +26,95 @@ function nodeToElements(node: DocNode): AdaptiveElement[] {
34
26
  const elements: AdaptiveElement[] = []
35
27
 
36
28
  switch (node.type) {
37
- case 'document':
38
- case 'page':
39
- case 'section':
40
- case 'row':
41
- case 'column':
29
+ case "document":
30
+ case "page":
31
+ case "section":
32
+ case "row":
33
+ case "column":
42
34
  for (const child of node.children) {
43
- if (typeof child !== 'string') {
35
+ if (typeof child !== "string") {
44
36
  elements.push(...nodeToElements(child))
45
37
  }
46
38
  }
47
39
  break
48
40
 
49
- case 'heading': {
41
+ case "heading": {
50
42
  const level = (p.level as number) ?? 1
51
43
  const sizeMap: Record<number, string> = {
52
- 1: 'extraLarge',
53
- 2: 'large',
54
- 3: 'medium',
55
- 4: 'default',
56
- 5: 'small',
57
- 6: 'small',
44
+ 1: "extraLarge",
45
+ 2: "large",
46
+ 3: "medium",
47
+ 4: "default",
48
+ 5: "small",
49
+ 6: "small",
58
50
  }
59
51
  elements.push({
60
- type: 'TextBlock',
52
+ type: "TextBlock",
61
53
  text: getTextContent(node.children),
62
- size: sizeMap[level] ?? 'large',
63
- weight: 'bolder',
54
+ size: sizeMap[level] ?? "large",
55
+ weight: "bolder",
64
56
  wrap: true,
65
57
  })
66
58
  break
67
59
  }
68
60
 
69
- case 'text': {
61
+ case "text": {
70
62
  let text = getTextContent(node.children)
71
63
  if (p.bold) text = `**${text}**`
72
64
  if (p.italic) text = `_${text}_`
73
65
  if (p.strikethrough) text = `~~${text}~~`
74
66
  elements.push({
75
- type: 'TextBlock',
67
+ type: "TextBlock",
76
68
  text,
77
69
  wrap: true,
78
- ...(p.color ? { color: 'default' } : {}),
79
- ...(p.size
80
- ? { size: (p.size as number) >= 18 ? 'large' : 'default' }
81
- : {}),
70
+ ...(p.color ? { color: "default" } : {}),
71
+ ...(p.size ? { size: (p.size as number) >= 18 ? "large" : "default" } : {}),
82
72
  })
83
73
  break
84
74
  }
85
75
 
86
- case 'link': {
76
+ case "link": {
87
77
  const href = sanitizeHref(p.href as string)
88
78
  const text = getTextContent(node.children)
89
79
  elements.push({
90
- type: 'TextBlock',
80
+ type: "TextBlock",
91
81
  text: `[${text}](${href})`,
92
82
  wrap: true,
93
83
  })
94
84
  break
95
85
  }
96
86
 
97
- case 'image': {
87
+ case "image": {
98
88
  const src = sanitizeImageSrc(p.src as string)
99
- if (src.startsWith('http')) {
89
+ if (src.startsWith("http")) {
100
90
  elements.push({
101
- type: 'Image',
91
+ type: "Image",
102
92
  url: src,
103
- altText: (p.alt as string) ?? 'Image',
104
- size: 'large',
93
+ altText: (p.alt as string) ?? "Image",
94
+ size: "large",
105
95
  })
106
96
  }
107
97
  break
108
98
  }
109
99
 
110
- case 'table': {
111
- const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(
112
- resolveColumn,
113
- )
100
+ case "table": {
101
+ const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(resolveColumn)
114
102
  const rows = (p.rows ?? []) as (string | number)[][]
115
103
 
116
104
  // Adaptive Cards have native Table support (schema 1.5+)
117
105
  const tableColumns = columns.map((col) => ({
118
- type: 'Column',
119
- width: 'stretch',
106
+ type: "Column",
107
+ width: "stretch",
120
108
  items: [
121
109
  {
122
- type: 'TextBlock',
110
+ type: "TextBlock",
123
111
  text: `**${col.header}**`,
124
- weight: 'bolder',
112
+ weight: "bolder",
125
113
  wrap: true,
126
114
  },
127
115
  ...rows.map((row, i) => ({
128
- type: 'TextBlock',
129
- text: String(row[columns.indexOf(col)] ?? ''),
116
+ type: "TextBlock",
117
+ text: String(row[columns.indexOf(col)] ?? ""),
130
118
  wrap: true,
131
119
  separator: i === 0,
132
120
  })),
@@ -134,80 +122,80 @@ function nodeToElements(node: DocNode): AdaptiveElement[] {
134
122
  }))
135
123
 
136
124
  elements.push({
137
- type: 'ColumnSet',
125
+ type: "ColumnSet",
138
126
  columns: tableColumns,
139
127
  })
140
128
  break
141
129
  }
142
130
 
143
- case 'list': {
131
+ case "list": {
144
132
  const ordered = p.ordered as boolean | undefined
145
133
  const items = node.children
146
- .filter((c): c is DocNode => typeof c !== 'string')
134
+ .filter((c): c is DocNode => typeof c !== "string")
147
135
  .map((item, i) => {
148
- const prefix = ordered ? `${i + 1}.` : ''
136
+ const prefix = ordered ? `${i + 1}.` : ""
149
137
  return `${prefix} ${getTextContent(item.children)}`
150
138
  })
151
- .join('\n')
139
+ .join("\n")
152
140
  elements.push({
153
- type: 'TextBlock',
141
+ type: "TextBlock",
154
142
  text: items,
155
143
  wrap: true,
156
144
  })
157
145
  break
158
146
  }
159
147
 
160
- case 'code': {
148
+ case "code": {
161
149
  const text = getTextContent(node.children)
162
150
  elements.push({
163
- type: 'TextBlock',
151
+ type: "TextBlock",
164
152
  text: `\`\`\`\n${text}\n\`\`\``,
165
- fontType: 'monospace',
153
+ fontType: "monospace",
166
154
  wrap: true,
167
155
  })
168
156
  break
169
157
  }
170
158
 
171
- case 'divider':
172
- case 'page-break':
159
+ case "divider":
160
+ case "page-break":
173
161
  elements.push({
174
- type: 'TextBlock',
175
- text: ' ',
162
+ type: "TextBlock",
163
+ text: " ",
176
164
  separator: true,
177
165
  })
178
166
  break
179
167
 
180
- case 'spacer':
168
+ case "spacer":
181
169
  elements.push({
182
- type: 'TextBlock',
183
- text: ' ',
184
- spacing: 'large',
170
+ type: "TextBlock",
171
+ text: " ",
172
+ spacing: "large",
185
173
  })
186
174
  break
187
175
 
188
- case 'button': {
176
+ case "button": {
189
177
  elements.push({
190
- type: 'ActionSet',
178
+ type: "ActionSet",
191
179
  actions: [
192
180
  {
193
- type: 'Action.OpenUrl',
181
+ type: "Action.OpenUrl",
194
182
  title: getTextContent(node.children),
195
183
  url: sanitizeHref(p.href as string),
196
- style: 'positive',
184
+ style: "positive",
197
185
  },
198
186
  ],
199
187
  })
200
188
  break
201
189
  }
202
190
 
203
- case 'quote': {
191
+ case "quote": {
204
192
  const text = getTextContent(node.children)
205
193
  elements.push({
206
- type: 'Container',
207
- style: 'emphasis',
194
+ type: "Container",
195
+ style: "emphasis",
208
196
  items: [
209
197
  {
210
- type: 'TextBlock',
198
+ type: "TextBlock",
211
199
  text: `_${text}_`,
212
200
  wrap: true,
213
201
  isSubtle: true,
@@ -225,9 +213,9 @@ export const teamsRenderer: DocumentRenderer = {
225
213
  async render(node: DocNode, _options?: RenderOptions): Promise<string> {
226
214
  const body = nodeToElements(node)
227
215
  const card = {
228
- type: 'AdaptiveCard',
229
- $schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
230
- version: '1.5',
216
+ type: "AdaptiveCard",
217
+ $schema: "http://adaptivecards.io/schemas/adaptive-card.json",
218
+ version: "1.5",
231
219
  body,
232
220
  }
233
221
  return JSON.stringify(card, null, 2)