@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,76 @@
1
+ import { render } from './render'
2
+ import type { DocNode, RenderOptions } from './types'
3
+
4
+ const FORMAT_MAP: Record<string, string> = {
5
+ html: 'html',
6
+ htm: 'html',
7
+ pdf: 'pdf',
8
+ docx: 'docx',
9
+ doc: 'docx',
10
+ xlsx: 'xlsx',
11
+ xls: 'xlsx',
12
+ pptx: 'pptx',
13
+ ppt: 'pptx',
14
+ md: 'md',
15
+ txt: 'text',
16
+ csv: 'csv',
17
+ svg: 'svg',
18
+ }
19
+
20
+ const MIME_TYPES: Record<string, string> = {
21
+ html: 'text/html',
22
+ pdf: 'application/pdf',
23
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
24
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
25
+ pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
26
+ email: 'text/html',
27
+ md: 'text/markdown',
28
+ text: 'text/plain',
29
+ csv: 'text/csv',
30
+ svg: 'image/svg+xml',
31
+ }
32
+
33
+ /**
34
+ * Download a document in the browser.
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * await download(doc, 'report.pdf')
39
+ * await download(doc, 'report.docx')
40
+ * ```
41
+ */
42
+ export async function download(
43
+ node: DocNode,
44
+ filename: string,
45
+ options?: RenderOptions,
46
+ ): Promise<void> {
47
+ const ext = filename.split('.').pop()?.toLowerCase()
48
+ if (!ext) {
49
+ throw new Error(
50
+ '[@pyreon/document] Filename must have an extension (e.g., report.pdf).',
51
+ )
52
+ }
53
+
54
+ const format = FORMAT_MAP[ext]
55
+ if (!format) {
56
+ throw new Error(
57
+ `[@pyreon/document] Unknown file extension '.${ext}'. Supported: ${Object.keys(FORMAT_MAP).join(', ')}`,
58
+ )
59
+ }
60
+
61
+ const result = await render(node, format, options)
62
+
63
+ const blob =
64
+ result instanceof Uint8Array
65
+ ? new Blob([result as BlobPart])
66
+ : new Blob([result], {
67
+ type: MIME_TYPES[format] ?? 'application/octet-stream',
68
+ })
69
+
70
+ const url = URL.createObjectURL(blob)
71
+ const a = document.createElement('a')
72
+ a.href = url
73
+ a.download = filename
74
+ a.click()
75
+ URL.revokeObjectURL(url)
76
+ }
package/src/env.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ declare module 'pdfmake/build/pdfmake' {
2
+ const pdfMake: {
3
+ vfs: Record<string, string>
4
+ createPdf: (docDefinition: Record<string, unknown>) => {
5
+ getBuffer: (callback: (buffer: ArrayBuffer) => void) => void
6
+ }
7
+ }
8
+ export default pdfMake
9
+ }
10
+
11
+ declare module 'pdfmake/build/vfs_fonts' {
12
+ const fonts: {
13
+ pdfMake?: { vfs: Record<string, string> }
14
+ vfs?: Record<string, string>
15
+ }
16
+ export default fonts
17
+ }
package/src/index.ts ADDED
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @pyreon/document — Universal document rendering for Pyreon.
3
+ *
4
+ * One template, every output format: HTML, PDF, DOCX, email, XLSX,
5
+ * Markdown, plain text, CSV, and custom formats.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { Document, Page, Heading, Text, Table, render } from '@pyreon/document'
10
+ *
11
+ * const doc = (
12
+ * <Document title="Report">
13
+ * <Page>
14
+ * <Heading>Sales Report</Heading>
15
+ * <Text>Q4 2026 performance summary.</Text>
16
+ * <Table
17
+ * columns={['Region', 'Revenue']}
18
+ * rows={[['US', '$1M'], ['EU', '$800K']]}
19
+ * />
20
+ * </Page>
21
+ * </Document>
22
+ * )
23
+ *
24
+ * await render(doc, 'pdf') // → PDF Uint8Array
25
+ * await render(doc, 'email') // → email-safe HTML string
26
+ * await render(doc, 'md') // → Markdown string
27
+ * ```
28
+ */
29
+
30
+ // Builder
31
+ export { createDocument } from './builder'
32
+
33
+ // Primitives
34
+ export {
35
+ Button,
36
+ Code,
37
+ Column,
38
+ Divider,
39
+ Document,
40
+ Heading,
41
+ Image,
42
+ isDocNode,
43
+ Link,
44
+ List,
45
+ ListItem,
46
+ Page,
47
+ PageBreak,
48
+ Quote,
49
+ Row,
50
+ Section,
51
+ Spacer,
52
+ Table,
53
+ Text,
54
+ } from './nodes'
55
+
56
+ // Download (browser)
57
+ export { download } from './download'
58
+
59
+ // Render
60
+ export {
61
+ _resetRenderers,
62
+ registerRenderer,
63
+ render,
64
+ unregisterRenderer,
65
+ } from './render'
66
+
67
+ // Types
68
+ export type {
69
+ ButtonProps,
70
+ CodeProps,
71
+ ColumnProps,
72
+ DividerProps,
73
+ DocChild,
74
+ DocNode,
75
+ DocumentBuilder,
76
+ DocumentProps,
77
+ DocumentRenderer,
78
+ HeadingProps,
79
+ ImageProps,
80
+ LinkProps,
81
+ ListItemProps,
82
+ ListProps,
83
+ NodeType,
84
+ OutputFormat,
85
+ PageOrientation,
86
+ PageProps,
87
+ PageSize,
88
+ QuoteProps,
89
+ RenderOptions,
90
+ RenderResult,
91
+ ResolvedStyles,
92
+ RowProps,
93
+ SectionProps,
94
+ SpacerProps,
95
+ TableColumn,
96
+ TableProps,
97
+ TextProps,
98
+ } from './types'
package/src/nodes.ts ADDED
@@ -0,0 +1,315 @@
1
+ import type {
2
+ ButtonProps,
3
+ CodeProps,
4
+ ColumnProps,
5
+ DividerProps,
6
+ DocChild,
7
+ DocNode,
8
+ DocumentProps,
9
+ HeadingProps,
10
+ ImageProps,
11
+ LinkProps,
12
+ ListItemProps,
13
+ ListProps,
14
+ NodeType,
15
+ PageProps,
16
+ QuoteProps,
17
+ RowProps,
18
+ SectionProps,
19
+ SpacerProps,
20
+ TableProps,
21
+ TextProps,
22
+ } from './types'
23
+
24
+ // ─── Node Constructor ───────────────────────────────────────────────────────
25
+
26
+ function createNode(type: NodeType, props: object, children: unknown): DocNode {
27
+ return {
28
+ type,
29
+ props: props as Record<string, unknown>,
30
+ children: normalizeChildren(children),
31
+ }
32
+ }
33
+
34
+ function normalizeChildren(children: unknown): DocChild[] {
35
+ if (children == null || children === false) return []
36
+ if (typeof children === 'string') return [children]
37
+ if (typeof children === 'number') return [String(children)]
38
+ if (Array.isArray(children)) return children.flatMap(normalizeChildren)
39
+ if (isDocNode(children)) return [children]
40
+ return [String(children)]
41
+ }
42
+
43
+ /** Type guard — checks if a value is a DocNode. */
44
+ export function isDocNode(value: unknown): value is DocNode {
45
+ return (
46
+ typeof value === 'object' &&
47
+ value !== null &&
48
+ 'type' in value &&
49
+ 'props' in value &&
50
+ 'children' in value
51
+ )
52
+ }
53
+
54
+ // ─── Document Primitives ────────────────────────────────────────────────────
55
+
56
+ /**
57
+ * Root document container. Holds metadata and pages.
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * <Document title="Invoice #1234" author="Acme Corp">
62
+ * <Page>...</Page>
63
+ * </Document>
64
+ * ```
65
+ */
66
+ export function Document(props: DocumentProps): DocNode {
67
+ const { children, ...rest } = props
68
+ return createNode('document', rest, children)
69
+ }
70
+ Document._documentType = 'document' as const
71
+
72
+ /**
73
+ * Page container. Maps to a PDF page, DOCX section, or email block.
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * <Page size="A4" margin={40}>
78
+ * <Heading>Title</Heading>
79
+ * </Page>
80
+ * ```
81
+ */
82
+ export function Page(props: PageProps): DocNode {
83
+ const { children, ...rest } = props
84
+ return createNode('page', rest, children)
85
+ }
86
+ Page._documentType = 'page' as const
87
+
88
+ /**
89
+ * Layout section — groups content with optional direction, padding, background.
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * <Section background="#f5f5f5" padding={20} direction="row" gap={12}>
94
+ * <Text>Left</Text>
95
+ * <Text>Right</Text>
96
+ * </Section>
97
+ * ```
98
+ */
99
+ export function Section(props: SectionProps): DocNode {
100
+ const { children, ...rest } = props
101
+ return createNode('section', rest, children)
102
+ }
103
+ Section._documentType = 'section' as const
104
+
105
+ /**
106
+ * Horizontal layout container.
107
+ *
108
+ * @example
109
+ * ```tsx
110
+ * <Row gap={20}>
111
+ * <Column width="60%"><Text>Main</Text></Column>
112
+ * <Column width="40%"><Text>Side</Text></Column>
113
+ * </Row>
114
+ * ```
115
+ */
116
+ export function Row(props: RowProps): DocNode {
117
+ const { children, ...rest } = props
118
+ return createNode('row', rest, children)
119
+ }
120
+ Row._documentType = 'row' as const
121
+
122
+ /**
123
+ * Column within a Row.
124
+ */
125
+ export function Column(props: ColumnProps): DocNode {
126
+ const { children, ...rest } = props
127
+ return createNode('column', rest, children)
128
+ }
129
+ Column._documentType = 'column' as const
130
+
131
+ /**
132
+ * Heading text (h1–h6).
133
+ *
134
+ * @example
135
+ * ```tsx
136
+ * <Heading level={1}>Invoice #1234</Heading>
137
+ * <Heading level={2} color="#666">Details</Heading>
138
+ * ```
139
+ */
140
+ export function Heading(props: HeadingProps): DocNode {
141
+ const { children, ...rest } = props
142
+ return createNode('heading', { level: 1, ...rest }, children)
143
+ }
144
+ Heading._documentType = 'heading' as const
145
+
146
+ /**
147
+ * Text paragraph with optional formatting.
148
+ *
149
+ * @example
150
+ * ```tsx
151
+ * <Text bold size={14} color="#333">Hello World</Text>
152
+ * <Text italic align="right">Subtotal: $100</Text>
153
+ * ```
154
+ */
155
+ export function Text(props: TextProps): DocNode {
156
+ const { children, ...rest } = props
157
+ return createNode('text', rest, children)
158
+ }
159
+ Text._documentType = 'text' as const
160
+
161
+ /**
162
+ * Hyperlink.
163
+ *
164
+ * @example
165
+ * ```tsx
166
+ * <Link href="https://example.com">Visit site</Link>
167
+ * ```
168
+ */
169
+ export function Link(props: LinkProps): DocNode {
170
+ const { children, ...rest } = props
171
+ return createNode('link', rest, children)
172
+ }
173
+ Link._documentType = 'link' as const
174
+
175
+ /**
176
+ * Image with optional sizing and caption.
177
+ *
178
+ * @example
179
+ * ```tsx
180
+ * <Image src="/logo.png" width={120} alt="Company Logo" />
181
+ * <Image src={chartDataUrl} width={500} caption="Revenue Chart" />
182
+ * ```
183
+ */
184
+ export function Image(props: ImageProps): DocNode {
185
+ return createNode('image', props, [])
186
+ }
187
+ Image._documentType = 'image' as const
188
+
189
+ /**
190
+ * Data table with columns and rows.
191
+ *
192
+ * @example
193
+ * ```tsx
194
+ * <Table
195
+ * columns={['Name', 'Price', 'Qty']}
196
+ * rows={[['Widget', '$10', '5'], ['Gadget', '$20', '3']]}
197
+ * striped
198
+ * headerStyle={{ background: '#1a1a2e', color: '#fff' }}
199
+ * />
200
+ * ```
201
+ */
202
+ export function Table(props: TableProps): DocNode {
203
+ return createNode('table', props, [])
204
+ }
205
+ Table._documentType = 'table' as const
206
+
207
+ /**
208
+ * Ordered or unordered list.
209
+ *
210
+ * @example
211
+ * ```tsx
212
+ * <List ordered>
213
+ * <ListItem>First item</ListItem>
214
+ * <ListItem>Second item</ListItem>
215
+ * </List>
216
+ * ```
217
+ */
218
+ export function List(props: ListProps): DocNode {
219
+ const { children, ...rest } = props
220
+ return createNode('list', rest, children)
221
+ }
222
+ List._documentType = 'list' as const
223
+
224
+ /**
225
+ * Single list item within a List.
226
+ */
227
+ export function ListItem(props: ListItemProps): DocNode {
228
+ const { children } = props
229
+ return createNode('list-item', {}, children)
230
+ }
231
+ ListItem._documentType = 'list-item' as const
232
+
233
+ /**
234
+ * Code block with optional language hint.
235
+ *
236
+ * @example
237
+ * ```tsx
238
+ * <Code language="typescript">const x = 42</Code>
239
+ * ```
240
+ */
241
+ export function Code(props: CodeProps): DocNode {
242
+ const { children, ...rest } = props
243
+ return createNode('code', rest, children)
244
+ }
245
+ Code._documentType = 'code' as const
246
+
247
+ /**
248
+ * Horizontal divider line.
249
+ *
250
+ * @example
251
+ * ```tsx
252
+ * <Divider color="#ddd" thickness={2} />
253
+ * ```
254
+ */
255
+ export function Divider(props: DividerProps = {}): DocNode {
256
+ return createNode('divider', props, [])
257
+ }
258
+ Divider._documentType = 'divider' as const
259
+
260
+ /**
261
+ * Page break — forces content after this point to the next page (PDF/DOCX)
262
+ * or inserts a visual separator (HTML/email).
263
+ *
264
+ * @example
265
+ * ```tsx
266
+ * <PageBreak />
267
+ * ```
268
+ */
269
+ export function PageBreak(): DocNode {
270
+ return createNode('page-break', {}, [])
271
+ }
272
+ PageBreak._documentType = 'page-break' as const
273
+
274
+ /**
275
+ * Vertical spacer.
276
+ *
277
+ * @example
278
+ * ```tsx
279
+ * <Spacer height={20} />
280
+ * ```
281
+ */
282
+ export function Spacer(props: SpacerProps): DocNode {
283
+ return createNode('spacer', props, [])
284
+ }
285
+ Spacer._documentType = 'spacer' as const
286
+
287
+ /**
288
+ * CTA button — renders as a bulletproof button in email, styled link in PDF/DOCX.
289
+ *
290
+ * @example
291
+ * ```tsx
292
+ * <Button href="https://acme.com/pay" background="#4f46e5" color="#fff">
293
+ * Pay Now
294
+ * </Button>
295
+ * ```
296
+ */
297
+ export function Button(props: ButtonProps): DocNode {
298
+ const { children, ...rest } = props
299
+ return createNode('button', rest, children)
300
+ }
301
+ Button._documentType = 'button' as const
302
+
303
+ /**
304
+ * Block quote.
305
+ *
306
+ * @example
307
+ * ```tsx
308
+ * <Quote borderColor="#4f46e5">This is a quote.</Quote>
309
+ * ```
310
+ */
311
+ export function Quote(props: QuoteProps): DocNode {
312
+ const { children, ...rest } = props
313
+ return createNode('quote', rest, children)
314
+ }
315
+ Quote._documentType = 'quote' as const