@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
package/src/download.ts
ADDED
|
@@ -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
|