@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.
- package/LICENSE +21 -0
- package/lib/analysis/index.js.html +5406 -0
- package/lib/chunk-ErZ26oRB.js +48 -0
- package/lib/confluence-Va8e7RxQ.js +192 -0
- package/lib/confluence-Va8e7RxQ.js.map +1 -0
- package/lib/csv-2c38ub-Y.js +32 -0
- package/lib/csv-2c38ub-Y.js.map +1 -0
- package/lib/discord-DAoUZqvE.js +134 -0
- package/lib/discord-DAoUZqvE.js.map +1 -0
- package/lib/dist-BsqdI2nY.js +20179 -0
- package/lib/dist-BsqdI2nY.js.map +1 -0
- package/lib/docx-CorFwEH9.js +450 -0
- package/lib/docx-CorFwEH9.js.map +1 -0
- package/lib/email-Bn_Brjdp.js +131 -0
- package/lib/email-Bn_Brjdp.js.map +1 -0
- package/lib/exceljs-BoIDUUaw.js +34377 -0
- package/lib/exceljs-BoIDUUaw.js.map +1 -0
- package/lib/google-chat-B6I017I1.js +125 -0
- package/lib/google-chat-B6I017I1.js.map +1 -0
- package/lib/html-De_iS_f0.js +151 -0
- package/lib/html-De_iS_f0.js.map +1 -0
- package/lib/index.js +619 -0
- package/lib/index.js.map +1 -0
- package/lib/markdown-BYC_3C9i.js +75 -0
- package/lib/markdown-BYC_3C9i.js.map +1 -0
- package/lib/notion-DHaQHO6P.js +187 -0
- package/lib/notion-DHaQHO6P.js.map +1 -0
- package/lib/pdf-CDPc5Itc.js +419 -0
- package/lib/pdf-CDPc5Itc.js.map +1 -0
- package/lib/pdfmake-DnmLxK4Q.js +55511 -0
- package/lib/pdfmake-DnmLxK4Q.js.map +1 -0
- package/lib/pptx-DKQU6bjq.js +252 -0
- package/lib/pptx-DKQU6bjq.js.map +1 -0
- package/lib/pptxgen.es-COcgXsyx.js +5697 -0
- package/lib/pptxgen.es-COcgXsyx.js.map +1 -0
- package/lib/slack-CJRJgkag.js +139 -0
- package/lib/slack-CJRJgkag.js.map +1 -0
- package/lib/svg-BM8biZmL.js +187 -0
- package/lib/svg-BM8biZmL.js.map +1 -0
- package/lib/teams-S99tonRG.js +176 -0
- package/lib/teams-S99tonRG.js.map +1 -0
- package/lib/telegram-CbEO_2PN.js +77 -0
- package/lib/telegram-CbEO_2PN.js.map +1 -0
- package/lib/text-B5U8ucRr.js +75 -0
- package/lib/text-B5U8ucRr.js.map +1 -0
- package/lib/types/index.d.ts +528 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/vfs_fonts-Df1kkZ4Y.js +19 -0
- package/lib/vfs_fonts-Df1kkZ4Y.js.map +1 -0
- package/lib/whatsapp-DJ2D1jGG.js +64 -0
- package/lib/whatsapp-DJ2D1jGG.js.map +1 -0
- package/lib/xlsx-D47x-gZ5.js +199 -0
- package/lib/xlsx-D47x-gZ5.js.map +1 -0
- package/package.json +62 -0
- package/src/builder.ts +266 -0
- package/src/download.ts +76 -0
- package/src/env.d.ts +17 -0
- package/src/index.ts +98 -0
- package/src/nodes.ts +315 -0
- package/src/render.ts +222 -0
- package/src/renderers/confluence.ts +231 -0
- package/src/renderers/csv.ts +67 -0
- package/src/renderers/discord.ts +192 -0
- package/src/renderers/docx.ts +612 -0
- package/src/renderers/email.ts +230 -0
- package/src/renderers/google-chat.ts +211 -0
- package/src/renderers/html.ts +225 -0
- package/src/renderers/markdown.ts +144 -0
- package/src/renderers/notion.ts +264 -0
- package/src/renderers/pdf.ts +427 -0
- package/src/renderers/pptx.ts +353 -0
- package/src/renderers/slack.ts +192 -0
- package/src/renderers/svg.ts +254 -0
- package/src/renderers/teams.ts +234 -0
- package/src/renderers/telegram.ts +137 -0
- package/src/renderers/text.ts +154 -0
- package/src/renderers/whatsapp.ts +121 -0
- package/src/renderers/xlsx.ts +342 -0
- package/src/tests/document.test.ts +2920 -0
- 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 = ``
|
|
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
|
+
}
|