@pyreon/document 0.0.1

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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/lib/analysis/index.js.html +5406 -0
  3. package/lib/chunk-ErZ26oRB.js +48 -0
  4. package/lib/confluence-Va8e7RxQ.js +192 -0
  5. package/lib/confluence-Va8e7RxQ.js.map +1 -0
  6. package/lib/csv-2c38ub-Y.js +32 -0
  7. package/lib/csv-2c38ub-Y.js.map +1 -0
  8. package/lib/discord-DAoUZqvE.js +134 -0
  9. package/lib/discord-DAoUZqvE.js.map +1 -0
  10. package/lib/dist-BsqdI2nY.js +20179 -0
  11. package/lib/dist-BsqdI2nY.js.map +1 -0
  12. package/lib/docx-CorFwEH9.js +450 -0
  13. package/lib/docx-CorFwEH9.js.map +1 -0
  14. package/lib/email-Bn_Brjdp.js +131 -0
  15. package/lib/email-Bn_Brjdp.js.map +1 -0
  16. package/lib/exceljs-BoIDUUaw.js +34377 -0
  17. package/lib/exceljs-BoIDUUaw.js.map +1 -0
  18. package/lib/google-chat-B6I017I1.js +125 -0
  19. package/lib/google-chat-B6I017I1.js.map +1 -0
  20. package/lib/html-De_iS_f0.js +151 -0
  21. package/lib/html-De_iS_f0.js.map +1 -0
  22. package/lib/index.js +619 -0
  23. package/lib/index.js.map +1 -0
  24. package/lib/markdown-BYC_3C9i.js +75 -0
  25. package/lib/markdown-BYC_3C9i.js.map +1 -0
  26. package/lib/notion-DHaQHO6P.js +187 -0
  27. package/lib/notion-DHaQHO6P.js.map +1 -0
  28. package/lib/pdf-CDPc5Itc.js +419 -0
  29. package/lib/pdf-CDPc5Itc.js.map +1 -0
  30. package/lib/pdfmake-DnmLxK4Q.js +55511 -0
  31. package/lib/pdfmake-DnmLxK4Q.js.map +1 -0
  32. package/lib/pptx-DKQU6bjq.js +252 -0
  33. package/lib/pptx-DKQU6bjq.js.map +1 -0
  34. package/lib/pptxgen.es-COcgXsyx.js +5697 -0
  35. package/lib/pptxgen.es-COcgXsyx.js.map +1 -0
  36. package/lib/slack-CJRJgkag.js +139 -0
  37. package/lib/slack-CJRJgkag.js.map +1 -0
  38. package/lib/svg-BM8biZmL.js +187 -0
  39. package/lib/svg-BM8biZmL.js.map +1 -0
  40. package/lib/teams-S99tonRG.js +176 -0
  41. package/lib/teams-S99tonRG.js.map +1 -0
  42. package/lib/telegram-CbEO_2PN.js +77 -0
  43. package/lib/telegram-CbEO_2PN.js.map +1 -0
  44. package/lib/text-B5U8ucRr.js +75 -0
  45. package/lib/text-B5U8ucRr.js.map +1 -0
  46. package/lib/types/index.d.ts +528 -0
  47. package/lib/types/index.d.ts.map +1 -0
  48. package/lib/vfs_fonts-Df1kkZ4Y.js +19 -0
  49. package/lib/vfs_fonts-Df1kkZ4Y.js.map +1 -0
  50. package/lib/whatsapp-DJ2D1jGG.js +64 -0
  51. package/lib/whatsapp-DJ2D1jGG.js.map +1 -0
  52. package/lib/xlsx-D47x-gZ5.js +199 -0
  53. package/lib/xlsx-D47x-gZ5.js.map +1 -0
  54. package/package.json +62 -0
  55. package/src/builder.ts +266 -0
  56. package/src/download.ts +76 -0
  57. package/src/env.d.ts +17 -0
  58. package/src/index.ts +98 -0
  59. package/src/nodes.ts +315 -0
  60. package/src/render.ts +222 -0
  61. package/src/renderers/confluence.ts +231 -0
  62. package/src/renderers/csv.ts +67 -0
  63. package/src/renderers/discord.ts +192 -0
  64. package/src/renderers/docx.ts +612 -0
  65. package/src/renderers/email.ts +230 -0
  66. package/src/renderers/google-chat.ts +211 -0
  67. package/src/renderers/html.ts +225 -0
  68. package/src/renderers/markdown.ts +144 -0
  69. package/src/renderers/notion.ts +264 -0
  70. package/src/renderers/pdf.ts +427 -0
  71. package/src/renderers/pptx.ts +353 -0
  72. package/src/renderers/slack.ts +192 -0
  73. package/src/renderers/svg.ts +254 -0
  74. package/src/renderers/teams.ts +234 -0
  75. package/src/renderers/telegram.ts +137 -0
  76. package/src/renderers/text.ts +154 -0
  77. package/src/renderers/whatsapp.ts +121 -0
  78. package/src/renderers/xlsx.ts +342 -0
  79. package/src/tests/document.test.ts +2920 -0
  80. package/src/types.ts +291 -0
@@ -0,0 +1,144 @@
1
+ import type {
2
+ DocChild,
3
+ DocNode,
4
+ DocumentRenderer,
5
+ RenderOptions,
6
+ TableColumn,
7
+ } from '../types'
8
+
9
+ function resolveColumn(col: string | TableColumn): TableColumn {
10
+ return typeof col === 'string' ? { header: col } : col
11
+ }
12
+
13
+ function renderChild(child: DocChild): string {
14
+ if (typeof child === 'string') return child
15
+ return renderNode(child)
16
+ }
17
+
18
+ function renderChildren(children: DocChild[]): string {
19
+ return children.map(renderChild).join('')
20
+ }
21
+
22
+ function renderInline(children: DocChild[]): string {
23
+ return children.map(renderChild).join('')
24
+ }
25
+
26
+ function renderNode(node: DocNode): string {
27
+ const p = node.props
28
+
29
+ switch (node.type) {
30
+ case 'document':
31
+ return renderChildren(node.children)
32
+
33
+ case 'page':
34
+ return renderChildren(node.children)
35
+
36
+ case 'section':
37
+ return `${renderChildren(node.children)}\n`
38
+
39
+ case 'row':
40
+ case 'column':
41
+ return renderChildren(node.children)
42
+
43
+ case 'heading': {
44
+ const level = (p.level as number) ?? 1
45
+ const prefix = '#'.repeat(Math.min(Math.max(level, 1), 6))
46
+ return `${prefix} ${renderInline(node.children)}\n\n`
47
+ }
48
+
49
+ case 'text': {
50
+ let text = renderInline(node.children)
51
+ if (p.bold) text = `**${text}**`
52
+ if (p.italic) text = `*${text}*`
53
+ if (p.strikethrough) text = `~~${text}~~`
54
+ return `${text}\n\n`
55
+ }
56
+
57
+ case 'link':
58
+ return `[${renderInline(node.children)}](${p.href})`
59
+
60
+ case 'image': {
61
+ const alt = (p.alt as string) ?? ''
62
+ let md = `![${alt}](${p.src})`
63
+ if (p.caption) md += `\n*${p.caption}*`
64
+ return `${md}\n\n`
65
+ }
66
+
67
+ case 'table': {
68
+ const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(
69
+ resolveColumn,
70
+ )
71
+ const rows = (p.rows ?? []) as (string | number)[][]
72
+
73
+ if (columns.length === 0) return ''
74
+
75
+ // Header
76
+ const header = `| ${columns.map((c) => c.header).join(' | ')} |`
77
+
78
+ // Separator with alignment
79
+ const separator = `| ${columns
80
+ .map((c) => {
81
+ const align = c.align ?? 'left'
82
+ if (align === 'center') return ':---:'
83
+ if (align === 'right') return '---:'
84
+ return '---'
85
+ })
86
+ .join(' | ')} |`
87
+
88
+ // Rows
89
+ const body = rows
90
+ .map(
91
+ (row) => `| ${row.map((cell) => String(cell ?? '')).join(' | ')} |`,
92
+ )
93
+ .join('\n')
94
+
95
+ let md = `${header}\n${separator}\n${body}\n\n`
96
+ if (p.caption) md = `*${p.caption}*\n\n${md}`
97
+ return md
98
+ }
99
+
100
+ case 'list': {
101
+ const ordered = p.ordered as boolean | undefined
102
+ return `${node.children
103
+ .filter((c): c is DocNode => typeof c !== 'string')
104
+ .map((item, i) => {
105
+ const prefix = ordered ? `${i + 1}.` : '-'
106
+ return `${prefix} ${renderInline(item.children)}`
107
+ })
108
+ .join('\n')}\n\n`
109
+ }
110
+
111
+ case 'list-item':
112
+ return renderInline(node.children)
113
+
114
+ case 'code': {
115
+ const lang = (p.language as string) ?? ''
116
+ const content = renderInline(node.children)
117
+ return `\`\`\`${lang}\n${content}\n\`\`\`\n\n`
118
+ }
119
+
120
+ case 'divider':
121
+ return '---\n\n'
122
+
123
+ case 'page-break':
124
+ return '---\n\n'
125
+
126
+ case 'spacer':
127
+ return '\n'
128
+
129
+ case 'button':
130
+ return `[${renderInline(node.children)}](${p.href})\n\n`
131
+
132
+ case 'quote':
133
+ return `> ${renderInline(node.children)}\n\n`
134
+
135
+ default:
136
+ return renderChildren(node.children)
137
+ }
138
+ }
139
+
140
+ export const markdownRenderer: DocumentRenderer = {
141
+ async render(node: DocNode, _options?: RenderOptions): Promise<string> {
142
+ return `${renderNode(node).trim()}\n`
143
+ },
144
+ }
@@ -0,0 +1,264 @@
1
+ import type {
2
+ DocChild,
3
+ DocNode,
4
+ DocumentRenderer,
5
+ RenderOptions,
6
+ TableColumn,
7
+ } from '../types'
8
+
9
+ /**
10
+ * Notion renderer — outputs Notion Block JSON for the Notion API.
11
+ * Blocks can be appended to a page via `notion.blocks.children.append()`.
12
+ */
13
+
14
+ function resolveColumn(col: string | TableColumn): TableColumn {
15
+ return typeof col === 'string' ? { header: col } : col
16
+ }
17
+
18
+ function getTextContent(children: DocChild[]): string {
19
+ return children
20
+ .map((c) =>
21
+ typeof c === 'string' ? c : getTextContent((c as DocNode).children),
22
+ )
23
+ .join('')
24
+ }
25
+
26
+ interface RichText {
27
+ type: 'text'
28
+ text: { content: string; link?: { url: string } }
29
+ annotations?: {
30
+ bold?: boolean
31
+ italic?: boolean
32
+ strikethrough?: boolean
33
+ underline?: boolean
34
+ code?: boolean
35
+ }
36
+ }
37
+
38
+ function textToRichText(
39
+ text: string,
40
+ annotations?: RichText['annotations'],
41
+ ): RichText[] {
42
+ return [
43
+ {
44
+ type: 'text',
45
+ text: { content: text },
46
+ ...(annotations ? { annotations } : {}),
47
+ },
48
+ ]
49
+ }
50
+
51
+ interface NotionBlock {
52
+ object: 'block'
53
+ type: string
54
+ [key: string]: unknown
55
+ }
56
+
57
+ function nodeToBlocks(node: DocNode): NotionBlock[] {
58
+ const p = node.props
59
+ const blocks: NotionBlock[] = []
60
+
61
+ switch (node.type) {
62
+ case 'document':
63
+ case 'page':
64
+ case 'section':
65
+ case 'row':
66
+ case 'column':
67
+ for (const child of node.children) {
68
+ if (typeof child !== 'string') {
69
+ blocks.push(...nodeToBlocks(child))
70
+ }
71
+ }
72
+ break
73
+
74
+ case 'heading': {
75
+ const level = (p.level as number) ?? 1
76
+ const text = getTextContent(node.children)
77
+ const type =
78
+ level <= 1 ? 'heading_1' : level === 2 ? 'heading_2' : 'heading_3'
79
+ blocks.push({
80
+ object: 'block',
81
+ type,
82
+ [type]: { rich_text: textToRichText(text) },
83
+ })
84
+ break
85
+ }
86
+
87
+ case 'text': {
88
+ const text = getTextContent(node.children)
89
+ const annotations: RichText['annotations'] = {}
90
+ if (p.bold) annotations.bold = true
91
+ if (p.italic) annotations.italic = true
92
+ if (p.strikethrough) annotations.strikethrough = true
93
+ if (p.underline) annotations.underline = true
94
+ blocks.push({
95
+ object: 'block',
96
+ type: 'paragraph',
97
+ paragraph: {
98
+ rich_text: textToRichText(
99
+ text,
100
+ Object.keys(annotations).length > 0 ? annotations : undefined,
101
+ ),
102
+ },
103
+ })
104
+ break
105
+ }
106
+
107
+ case 'link': {
108
+ const href = p.href as string
109
+ const text = getTextContent(node.children)
110
+ blocks.push({
111
+ object: 'block',
112
+ type: 'paragraph',
113
+ paragraph: {
114
+ rich_text: [
115
+ { type: 'text', text: { content: text, link: { url: href } } },
116
+ ],
117
+ },
118
+ })
119
+ break
120
+ }
121
+
122
+ case 'image': {
123
+ const src = p.src as string
124
+ if (src.startsWith('http')) {
125
+ blocks.push({
126
+ object: 'block',
127
+ type: 'image',
128
+ image: {
129
+ type: 'external',
130
+ external: { url: src },
131
+ ...(p.caption
132
+ ? { caption: textToRichText(p.caption as string) }
133
+ : {}),
134
+ },
135
+ })
136
+ }
137
+ break
138
+ }
139
+
140
+ case 'table': {
141
+ const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(
142
+ resolveColumn,
143
+ )
144
+ const rows = (p.rows ?? []) as (string | number)[][]
145
+
146
+ const tableRows: NotionBlock[] = []
147
+
148
+ // Header row
149
+ tableRows.push({
150
+ object: 'block',
151
+ type: 'table_row',
152
+ table_row: {
153
+ cells: columns.map((col) =>
154
+ textToRichText(col.header, { bold: true }),
155
+ ),
156
+ },
157
+ })
158
+
159
+ // Data rows
160
+ for (const row of rows) {
161
+ tableRows.push({
162
+ object: 'block',
163
+ type: 'table_row',
164
+ table_row: {
165
+ cells: columns.map((_, i) => textToRichText(String(row[i] ?? ''))),
166
+ },
167
+ })
168
+ }
169
+
170
+ blocks.push({
171
+ object: 'block',
172
+ type: 'table',
173
+ table: {
174
+ table_width: columns.length,
175
+ has_column_header: true,
176
+ children: tableRows,
177
+ },
178
+ })
179
+ break
180
+ }
181
+
182
+ case 'list': {
183
+ const ordered = p.ordered as boolean | undefined
184
+ const items = node.children.filter(
185
+ (c): c is DocNode => typeof c !== 'string',
186
+ )
187
+ for (const item of items) {
188
+ const text = getTextContent(item.children)
189
+ const type = ordered ? 'numbered_list_item' : 'bulleted_list_item'
190
+ blocks.push({
191
+ object: 'block',
192
+ type,
193
+ [type]: { rich_text: textToRichText(text) },
194
+ })
195
+ }
196
+ break
197
+ }
198
+
199
+ case 'code': {
200
+ const text = getTextContent(node.children)
201
+ const lang = (p.language as string) ?? 'plain text'
202
+ blocks.push({
203
+ object: 'block',
204
+ type: 'code',
205
+ code: {
206
+ rich_text: textToRichText(text),
207
+ language: lang,
208
+ },
209
+ })
210
+ break
211
+ }
212
+
213
+ case 'divider':
214
+ case 'page-break':
215
+ blocks.push({ object: 'block', type: 'divider', divider: {} })
216
+ break
217
+
218
+ case 'spacer':
219
+ blocks.push({
220
+ object: 'block',
221
+ type: 'paragraph',
222
+ paragraph: { rich_text: [] },
223
+ })
224
+ break
225
+
226
+ case 'button': {
227
+ const href = p.href as string
228
+ const text = getTextContent(node.children)
229
+ blocks.push({
230
+ object: 'block',
231
+ type: 'paragraph',
232
+ paragraph: {
233
+ rich_text: [
234
+ {
235
+ type: 'text',
236
+ text: { content: text, link: { url: href } },
237
+ annotations: { bold: true },
238
+ },
239
+ ],
240
+ },
241
+ })
242
+ break
243
+ }
244
+
245
+ case 'quote': {
246
+ const text = getTextContent(node.children)
247
+ blocks.push({
248
+ object: 'block',
249
+ type: 'quote',
250
+ quote: { rich_text: textToRichText(text) },
251
+ })
252
+ break
253
+ }
254
+ }
255
+
256
+ return blocks
257
+ }
258
+
259
+ export const notionRenderer: DocumentRenderer = {
260
+ async render(node: DocNode, _options?: RenderOptions): Promise<string> {
261
+ const blocks = nodeToBlocks(node)
262
+ return JSON.stringify({ children: blocks }, null, 2)
263
+ },
264
+ }