@pyreon/document 0.7.0 → 0.8.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 (75) hide show
  1. package/lib/analysis/index.js.html +1 -1
  2. package/lib/{confluence-Va8e7RxQ.js → confluence-Bd3ua1Ut.js} +6 -4
  3. package/lib/confluence-Bd3ua1Ut.js.map +1 -0
  4. package/lib/{csv-2c38ub-Y.js → csv-COrS4qdy.js} +1 -1
  5. package/lib/{csv-2c38ub-Y.js.map → csv-COrS4qdy.js.map} +1 -1
  6. package/lib/{discord-DAoUZqvE.js → discord-BLUnkEh9.js} +6 -4
  7. package/lib/discord-BLUnkEh9.js.map +1 -0
  8. package/lib/{docx-CorFwEH9.js → docx-BEBOihjl.js} +27 -26
  9. package/lib/docx-BEBOihjl.js.map +1 -0
  10. package/lib/{email-Bn_Brjdp.js → email-D0bbfWq4.js} +15 -13
  11. package/lib/email-D0bbfWq4.js.map +1 -0
  12. package/lib/{google-chat-B6I017I1.js → google-chat-CkKCBUWC.js} +6 -4
  13. package/lib/google-chat-CkKCBUWC.js.map +1 -0
  14. package/lib/{html-De_iS_f0.js → html-B5biprN2.js} +15 -13
  15. package/lib/html-B5biprN2.js.map +1 -0
  16. package/lib/index.js +44 -42
  17. package/lib/index.js.map +1 -1
  18. package/lib/{markdown-BYC_3C9i.js → markdown-CdtlFGC0.js} +6 -4
  19. package/lib/markdown-CdtlFGC0.js.map +1 -0
  20. package/lib/{notion-DHaQHO6P.js → notion-iG2C5bEY.js} +6 -4
  21. package/lib/notion-iG2C5bEY.js.map +1 -0
  22. package/lib/{pdf-CDPc5Itc.js → pdf-DIUQUEdj.js} +1 -1
  23. package/lib/{pdf-CDPc5Itc.js.map → pdf-DIUQUEdj.js.map} +1 -1
  24. package/lib/{pptx-DKQU6bjq.js → pptx-Dd33oL3_.js} +13 -11
  25. package/lib/pptx-Dd33oL3_.js.map +1 -0
  26. package/lib/sanitize-O_3j1mNJ.js +73 -0
  27. package/lib/sanitize-O_3j1mNJ.js.map +1 -0
  28. package/lib/{slack-CJRJgkag.js → slack-BI3EQwYm.js} +6 -4
  29. package/lib/slack-BI3EQwYm.js.map +1 -0
  30. package/lib/{svg-BM8biZmL.js → svg-BKxumy-p.js} +14 -12
  31. package/lib/svg-BKxumy-p.js.map +1 -0
  32. package/lib/{teams-S99tonRG.js → teams-Cwz9lce0.js} +6 -4
  33. package/lib/teams-Cwz9lce0.js.map +1 -0
  34. package/lib/{telegram-CbEO_2PN.js → telegram-gYFqyMXb.js} +5 -3
  35. package/lib/telegram-gYFqyMXb.js.map +1 -0
  36. package/lib/{text-B5U8ucRr.js → text-l1XNXBOC.js} +1 -1
  37. package/lib/{text-B5U8ucRr.js.map → text-l1XNXBOC.js.map} +1 -1
  38. package/lib/types/index.d.ts.map +1 -1
  39. package/lib/{whatsapp-DJ2D1jGG.js → whatsapp-CjSGoOKx.js} +5 -3
  40. package/lib/whatsapp-CjSGoOKx.js.map +1 -0
  41. package/lib/{xlsx-D47x-gZ5.js → xlsx-Bb5TWyXQ.js} +1 -1
  42. package/lib/{xlsx-D47x-gZ5.js.map → xlsx-Bb5TWyXQ.js.map} +1 -1
  43. package/package.json +3 -3
  44. package/src/builder.ts +6 -6
  45. package/src/download.ts +6 -0
  46. package/src/nodes.ts +5 -0
  47. package/src/renderers/confluence.ts +4 -3
  48. package/src/renderers/discord.ts +4 -3
  49. package/src/renderers/docx.ts +44 -32
  50. package/src/renderers/email.ts +15 -12
  51. package/src/renderers/google-chat.ts +4 -3
  52. package/src/renderers/html.ts +20 -12
  53. package/src/renderers/markdown.ts +4 -3
  54. package/src/renderers/notion.ts +4 -3
  55. package/src/renderers/pptx.ts +11 -10
  56. package/src/renderers/slack.ts +4 -3
  57. package/src/renderers/svg.ts +12 -11
  58. package/src/renderers/teams.ts +4 -3
  59. package/src/renderers/telegram.ts +3 -2
  60. package/src/renderers/whatsapp.ts +3 -2
  61. package/src/sanitize.ts +88 -0
  62. package/lib/confluence-Va8e7RxQ.js.map +0 -1
  63. package/lib/discord-DAoUZqvE.js.map +0 -1
  64. package/lib/docx-CorFwEH9.js.map +0 -1
  65. package/lib/email-Bn_Brjdp.js.map +0 -1
  66. package/lib/google-chat-B6I017I1.js.map +0 -1
  67. package/lib/html-De_iS_f0.js.map +0 -1
  68. package/lib/markdown-BYC_3C9i.js.map +0 -1
  69. package/lib/notion-DHaQHO6P.js.map +0 -1
  70. package/lib/pptx-DKQU6bjq.js.map +0 -1
  71. package/lib/slack-CJRJgkag.js.map +0 -1
  72. package/lib/svg-BM8biZmL.js.map +0 -1
  73. package/lib/teams-S99tonRG.js.map +0 -1
  74. package/lib/telegram-CbEO_2PN.js.map +0 -1
  75. package/lib/whatsapp-DJ2D1jGG.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"email-Bn_Brjdp.js","names":[],"sources":["../src/renderers/email.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * Email renderer — generates table-based HTML with inline styles\n * that works across Gmail, Outlook, Apple Mail, and other email clients.\n *\n * Key constraints:\n * - No CSS classes (Gmail strips <style> tags)\n * - Table-based layout (no flexbox/grid)\n * - All styles inline\n * - VML buttons for Outlook\n * - Max width 600px for compatibility\n */\n\nfunction esc(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction renderChild(child: DocChild): string {\n if (typeof child === 'string') return esc(child)\n return renderNode(child)\n}\n\nfunction renderChildren(children: DocChild[]): string {\n return children.map(renderChild).join('')\n}\n\nfunction wrapInTable(content: string, style = ''): string {\n return `<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"${style ? ` style=\"${style}\"` : ''}><tr><td>${content}</td></tr></table>`\n}\n\nfunction renderNode(node: DocNode): string {\n const p = node.props\n\n switch (node.type) {\n case 'document': {\n const title = p.title ? `<title>${esc(p.title as string)}</title>` : ''\n const preview = p.subject\n ? `<div style=\"display:none;max-height:0;overflow:hidden\">${esc(p.subject as string)}</div>`\n : ''\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">${title}<!--[if mso]><noscript><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml></noscript><![endif]--></head><body style=\"margin:0;padding:0;background-color:#f4f4f4;font-family:Arial,Helvetica,sans-serif\">${preview}<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background-color:#f4f4f4\"><tr><td align=\"center\" style=\"padding:20px 0\"><table width=\"600\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background-color:#ffffff;max-width:600px;width:100%\"><tr><td>${renderChildren(node.children)}</td></tr></table></td></tr></table></body></html>`\n }\n\n case 'page':\n // In email, pages are just content sections\n return renderChildren(node.children)\n\n case 'section': {\n const bg = p.background ? `background-color:${p.background};` : ''\n const pad = p.padding\n ? `padding:${typeof p.padding === 'number' ? `${p.padding}px` : Array.isArray(p.padding) ? (p.padding as number[]).map((v) => `${v}px`).join(' ') : '0'}`\n : 'padding:0'\n const radius = p.borderRadius ? `border-radius:${p.borderRadius}px;` : ''\n\n if (p.direction === 'row') {\n // Row layout via nested table\n const children = node.children.filter(\n (c): c is DocNode => typeof c !== 'string',\n )\n const colWidth = Math.floor(100 / Math.max(children.length, 1))\n return `<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"${bg}${radius}${pad}\"><tr>${children.map((child) => `<td width=\"${colWidth}%\" valign=\"top\" style=\"padding:${(p.gap as number | undefined) ? `0 ${(p.gap as number) / 2}px` : '0'}\">${renderNode(child)}</td>`).join('')}</tr></table>`\n }\n\n return wrapInTable(renderChildren(node.children), `${bg}${radius}${pad}`)\n }\n\n case 'row': {\n const children = node.children.filter(\n (c): c is DocNode => typeof c !== 'string',\n )\n const gap = (p.gap as number) ?? 0\n return `<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>${children.map((child) => `<td valign=\"top\" style=\"padding:0 ${gap / 2}px\">${renderNode(child)}</td>`).join('')}</tr></table>`\n }\n\n case 'column':\n return renderChildren(node.children)\n\n case 'heading': {\n const level = (p.level as number) ?? 1\n const sizes: Record<number, number> = {\n 1: 28,\n 2: 24,\n 3: 20,\n 4: 18,\n 5: 16,\n 6: 14,\n }\n const size = sizes[level] ?? 24\n const color = (p.color as string) ?? '#000000'\n const align = (p.align as string) ?? 'left'\n return `<h${level} style=\"margin:0 0 12px 0;font-size:${size}px;color:${color};text-align:${align};font-weight:bold;line-height:1.3\">${renderChildren(node.children)}</h${level}>`\n }\n\n case 'text': {\n const size = (p.size as number) ?? 14\n const color = (p.color as string) ?? '#333333'\n const weight = p.bold ? 'bold' : 'normal'\n const style = p.italic ? 'italic' : 'normal'\n const decoration = p.underline\n ? 'underline'\n : p.strikethrough\n ? 'line-through'\n : 'none'\n const align = (p.align as string) ?? 'left'\n const lh = (p.lineHeight as number) ?? 1.5\n return `<p style=\"margin:0 0 12px 0;font-size:${size}px;color:${color};font-weight:${weight};font-style:${style};text-decoration:${decoration};text-align:${align};line-height:${lh}\">${renderChildren(node.children)}</p>`\n }\n\n case 'link':\n return `<a href=\"${esc(p.href as string)}\" style=\"color:${(p.color as string) ?? '#4f46e5'};text-decoration:underline\" target=\"_blank\">${renderChildren(node.children)}</a>`\n\n case 'image': {\n const align = (p.align as string) ?? 'left'\n const img = `<img src=\"${esc(p.src as string)}\"${p.width ? ` width=\"${p.width}\"` : ''}${p.height ? ` height=\"${p.height}\"` : ''} alt=\"${esc((p.alt as string) ?? '')}\" style=\"display:block;outline:none;border:none;text-decoration:none${p.width ? `;max-width:${p.width}px` : ''}\" />`\n if (p.caption) {\n return `<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\"${align === 'center' ? ' align=\"center\"' : ''}><tr><td>${img}</td></tr><tr><td style=\"font-size:12px;color:#666;padding-top:4px;text-align:center\">${esc(p.caption as string)}</td></tr></table>`\n }\n if (align === 'center')\n return `<div style=\"text-align:center\">${img}</div>`\n if (align === 'right') return `<div style=\"text-align:right\">${img}</div>`\n return img\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n const hs = p.headerStyle as\n | { background?: string; color?: string; bold?: boolean }\n | undefined\n const striped = p.striped as boolean | undefined\n\n let html =\n '<table width=\"100%\" cellpadding=\"8\" cellspacing=\"0\" border=\"0\" style=\"border-collapse:collapse\">'\n if (p.caption)\n html += `<caption style=\"font-size:12px;color:#666;padding:8px;text-align:left\">${esc(p.caption as string)}</caption>`\n\n html += '<tr>'\n for (const col of columns) {\n const bg = hs?.background\n ? `background-color:${hs.background};`\n : 'background-color:#f5f5f5;'\n const color = hs?.color ? `color:${hs.color};` : ''\n const align = col.align ? `text-align:${col.align};` : ''\n const width = col.width\n ? `width:${typeof col.width === 'number' ? `${col.width}px` : col.width};`\n : ''\n html += `<th style=\"${bg}${color}font-weight:bold;${align}${width}padding:8px;border-bottom:2px solid #ddd\">${esc(col.header)}</th>`\n }\n html += '</tr>'\n\n for (let i = 0; i < rows.length; i++) {\n const bg = striped && i % 2 === 1 ? 'background-color:#f9f9f9;' : ''\n html += '<tr>'\n for (let j = 0; j < columns.length; j++) {\n const col = columns[j]\n const align = col?.align ? `text-align:${col.align};` : ''\n html += `<td style=\"${bg}${align}padding:8px;border-bottom:1px solid #eee\">${esc(String(rows[i]?.[j] ?? ''))}</td>`\n }\n html += '</tr>'\n }\n html += '</table>'\n return html\n }\n\n case 'list': {\n const tag = p.ordered ? 'ol' : 'ul'\n return `<${tag} style=\"margin:0 0 12px 0;padding-left:24px\">${renderChildren(node.children)}</${tag}>`\n }\n\n case 'list-item':\n return `<li style=\"margin:0 0 4px 0;font-size:14px;color:#333\">${renderChildren(node.children)}</li>`\n\n case 'code':\n return `<pre style=\"background-color:#f5f5f5;padding:12px;border-radius:4px;font-family:Courier New,monospace;font-size:13px;color:#333;overflow-x:auto;margin:0 0 12px 0\"><code>${esc(renderChildren(node.children))}</code></pre>`\n\n case 'divider': {\n const color = (p.color as string) ?? '#dddddd'\n const thickness = (p.thickness as number) ?? 1\n return `<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:16px 0\"><tr><td style=\"border-top:${thickness}px solid ${color};font-size:0;line-height:0\">&nbsp;</td></tr></table>`\n }\n\n case 'page-break':\n return `<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:24px 0\"><tr><td style=\"border-top:2px solid #dddddd;font-size:0;line-height:0\">&nbsp;</td></tr></table>`\n\n case 'spacer':\n return `<div style=\"height:${p.height}px;line-height:${p.height}px;font-size:0\">&nbsp;</div>`\n\n case 'button': {\n const bg = (p.background as string) ?? '#4f46e5'\n const color = (p.color as string) ?? '#ffffff'\n const radius = (p.borderRadius as number) ?? 4\n const href = esc(p.href as string)\n const text = renderChildren(node.children)\n const align = (p.align as string) ?? 'left'\n\n // Bulletproof button — works in Outlook via VML, CSS everywhere else\n return `<div style=\"text-align:${align};margin:12px 0\"><!--[if mso]><v:roundrect xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" href=\"${href}\" style=\"height:44px;v-text-anchor:middle;width:200px\" arcsize=\"10%\" strokecolor=\"${bg}\" fillcolor=\"${bg}\"><w:anchorlock/><center style=\"color:${color};font-family:Arial,sans-serif;font-size:14px;font-weight:bold\">${text}</center></v:roundrect><![endif]--><!--[if !mso]><!--><a href=\"${href}\" style=\"display:inline-block;background-color:${bg};color:${color};padding:12px 24px;border-radius:${radius}px;text-decoration:none;font-weight:bold;font-size:14px;font-family:Arial,sans-serif\" target=\"_blank\">${text}</a><!--<![endif]--></div>`\n }\n\n case 'quote': {\n const borderColor = (p.borderColor as string) ?? '#dddddd'\n return `<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:12px 0\"><tr><td style=\"border-left:4px solid ${borderColor};padding:12px 20px;color:#555555;font-style:italic\">${renderChildren(node.children)}</td></tr></table>`\n }\n\n default:\n return renderChildren(node.children)\n }\n}\n\nexport const emailRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n return renderNode(node)\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"google-chat-B6I017I1.js","names":[],"sources":["../src/renderers/google-chat.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * Google Chat renderer — outputs Card V2 JSON for Google Chat API.\n * Cards can be sent via webhooks, Chat API, or Apps Script.\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\ninterface CardWidget {\n [key: string]: unknown\n}\n\nfunction nodeToWidgets(node: DocNode): CardWidget[] {\n const p = node.props\n const widgets: CardWidget[] = []\n\n switch (node.type) {\n case 'document':\n case 'page':\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n widgets.push(...nodeToWidgets(child))\n }\n }\n break\n\n case 'heading': {\n const text = getTextContent(node.children)\n widgets.push({\n decoratedText: {\n topLabel: '',\n text: `<b>${text}</b>`,\n wrapText: true,\n },\n })\n break\n }\n\n case 'text': {\n let text = getTextContent(node.children)\n if (p.bold) text = `<b>${text}</b>`\n if (p.italic) text = `<i>${text}</i>`\n if (p.strikethrough) text = `<s>${text}</s>`\n widgets.push({\n textParagraph: { text },\n })\n break\n }\n\n case 'link': {\n const href = p.href as string\n const text = getTextContent(node.children)\n widgets.push({\n textParagraph: { text: `<a href=\"${href}\">${text}</a>` },\n })\n break\n }\n\n case 'image': {\n const src = p.src as string\n if (src.startsWith('http')) {\n widgets.push({\n image: {\n imageUrl: src,\n altText: (p.alt as string) ?? 'Image',\n },\n })\n }\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n\n // Google Chat Cards don't have native tables — use grid or formatted text\n const header = columns.map((c) => `<b>${c.header}</b>`).join(' | ')\n const body = rows\n .map((row) => row.map((c) => String(c ?? '')).join(' | '))\n .join('\\n')\n\n widgets.push({\n textParagraph: { text: `${header}\\n${body}` },\n })\n break\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n const items = node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item, i) => {\n const prefix = ordered ? `${i + 1}.` : '•'\n return `${prefix} ${getTextContent(item.children)}`\n })\n .join('\\n')\n widgets.push({\n textParagraph: { text: items },\n })\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n widgets.push({\n textParagraph: {\n text: `<font color=\"#333333\"><code>${text}</code></font>`,\n },\n })\n break\n }\n\n case 'divider':\n case 'page-break':\n widgets.push({ divider: {} })\n break\n\n case 'spacer':\n // No direct equivalent — skip\n break\n\n case 'button': {\n const href = p.href as string\n const text = getTextContent(node.children)\n widgets.push({\n buttonList: {\n buttons: [\n {\n text,\n onClick: { openLink: { url: href } },\n color: {\n red: 0.31,\n green: 0.27,\n blue: 0.89,\n alpha: 1,\n },\n },\n ],\n },\n })\n break\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n widgets.push({\n textParagraph: { text: `<i>\"${text}\"</i>` },\n })\n break\n }\n }\n\n return widgets\n}\n\nexport const googleChatRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n const widgets = nodeToWidgets(node)\n\n // Extract title from first heading or document title\n let title = (node.props.title as string) ?? ''\n if (!title) {\n const firstHeading = node.children.find(\n (c): c is DocNode => typeof c !== 'string' && c.type === 'heading',\n )\n if (firstHeading) title = getTextContent(firstHeading.children)\n }\n\n const card = {\n cardsV2: [\n {\n cardId: 'document',\n card: {\n header: title\n ? { title, subtitle: (node.props.subject as string) ?? undefined }\n : undefined,\n sections: [\n {\n widgets,\n },\n ],\n },\n },\n ],\n }\n\n return JSON.stringify(card, null, 2)\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"html-De_iS_f0.js","names":[],"sources":["../src/renderers/html.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction styleStr(styles: Record<string, string | number | undefined>): string {\n const parts: string[] = []\n for (const [k, v] of Object.entries(styles)) {\n if (v != null && v !== '') {\n const prop = k.replace(/([A-Z])/g, '-$1').toLowerCase()\n parts.push(`${prop}:${typeof v === 'number' ? `${v}px` : v}`)\n }\n }\n return parts.length > 0 ? ` style=\"${parts.join(';')}\"` : ''\n}\n\nfunction padStr(\n pad: number | [number, number] | [number, number, number, number] | undefined,\n): string | undefined {\n if (pad == null) return undefined\n if (typeof pad === 'number') return `${pad}px`\n if (pad.length === 2) return `${pad[0]}px ${pad[1]}px`\n return `${pad[0]}px ${pad[1]}px ${pad[2]}px ${pad[3]}px`\n}\n\nfunction renderChild(child: DocChild): string {\n if (typeof child === 'string') return escapeHtml(child)\n return renderNode(child)\n}\n\nfunction renderChildren(children: DocChild[]): string {\n return children.map(renderChild).join('')\n}\n\nfunction renderNode(node: DocNode): string {\n const p = node.props\n\n switch (node.type) {\n case 'document': {\n const lang = (p.language as string) ?? 'en'\n const title = p.title\n ? `<title>${escapeHtml(p.title as string)}</title>`\n : ''\n return `<!DOCTYPE html><html lang=\"${lang}\"><head><meta charset=\"utf-8\">${title}<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"></head><body>${renderChildren(node.children)}</body></html>`\n }\n\n case 'page': {\n const margin = padStr(p.margin as PageMargin)\n return `<div${styleStr({ maxWidth: '800px', margin: margin ?? '0 auto', padding: margin ?? '40px' })}>${renderChildren(node.children)}</div>`\n }\n\n case 'section': {\n const dir = (p.direction as string) ?? 'column'\n return `<div${styleStr({\n display: dir === 'row' ? 'flex' : 'block',\n flexDirection: dir === 'row' ? 'row' : undefined,\n gap: p.gap as number | undefined,\n padding: padStr(p.padding as PageMargin),\n background: p.background as string | undefined,\n borderRadius: p.borderRadius as number | undefined,\n })}>${renderChildren(node.children)}</div>`\n }\n\n case 'row':\n return `<div${styleStr({ display: 'flex', gap: p.gap as number | undefined, alignItems: p.align as string | undefined })}>${renderChildren(node.children)}</div>`\n\n case 'column':\n return `<div${styleStr({ flex: p.width ? undefined : '1', width: p.width as string | undefined, textAlign: p.align as string | undefined })}>${renderChildren(node.children)}</div>`\n\n case 'heading': {\n const level = (p.level as number) ?? 1\n const tag = `h${Math.min(Math.max(level, 1), 6)}`\n return `<${tag}${styleStr({ color: p.color as string | undefined, textAlign: p.align as string | undefined })}>${renderChildren(node.children)}</${tag}>`\n }\n\n case 'text': {\n return `<p${styleStr({\n fontSize: p.size as number | undefined,\n color: p.color as string | undefined,\n fontWeight: p.bold ? 'bold' : undefined,\n fontStyle: p.italic ? 'italic' : undefined,\n textDecoration: p.underline\n ? 'underline'\n : p.strikethrough\n ? 'line-through'\n : undefined,\n textAlign: p.align as string | undefined,\n lineHeight: p.lineHeight as number | undefined,\n })}>${renderChildren(node.children)}</p>`\n }\n\n case 'link':\n return `<a href=\"${escapeHtml(p.href as string)}\"${styleStr({ color: p.color as string | undefined })}>${renderChildren(node.children)}</a>`\n\n case 'image': {\n const alignStyle =\n p.align === 'center'\n ? 'display:block;margin:0 auto'\n : p.align === 'right'\n ? 'display:block;margin-left:auto'\n : ''\n const img = `<img src=\"${escapeHtml(p.src as string)}\"${p.width ? ` width=\"${p.width}\"` : ''}${p.height ? ` height=\"${p.height}\"` : ''}${p.alt ? ` alt=\"${escapeHtml(p.alt as string)}\"` : ''}${alignStyle ? ` style=\"${alignStyle}\"` : ''} />`\n if (p.caption) {\n return `<figure${p.align === 'center' ? ' style=\"text-align:center\"' : ''}>${img}<figcaption>${escapeHtml(p.caption as string)}</figcaption></figure>`\n }\n return img\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n const hs = p.headerStyle as\n | { background?: string; color?: string; bold?: boolean }\n | undefined\n const striped = p.striped as boolean | undefined\n const bordered = p.bordered as boolean | undefined\n const borderStyle = bordered\n ? 'border:1px solid #ddd;border-collapse:collapse;'\n : 'border-collapse:collapse;'\n\n let html = `<table style=\"width:100%;${borderStyle}\">`\n if (p.caption)\n html += `<caption>${escapeHtml(p.caption as string)}</caption>`\n\n html += '<thead><tr>'\n for (const col of columns) {\n const cellBorder = bordered ? 'border:1px solid #ddd;' : ''\n const bgStyle = hs?.background ? `background:${hs.background};` : ''\n const colorStyle = hs?.color ? `color:${hs.color};` : ''\n const fontStyle = hs?.bold !== false ? 'font-weight:bold;' : ''\n const alignStyle = col.align ? `text-align:${col.align};` : ''\n const widthStyle = col.width\n ? `width:${typeof col.width === 'number' ? `${col.width}px` : col.width};`\n : ''\n html += `<th style=\"${cellBorder}${bgStyle}${colorStyle}${fontStyle}${alignStyle}${widthStyle}padding:8px\">${escapeHtml(col.header)}</th>`\n }\n html += '</tr></thead>'\n\n html += '<tbody>'\n for (let i = 0; i < rows.length; i++) {\n const rowBg =\n striped && i % 2 === 1 ? ' style=\"background:#f9f9f9\"' : ''\n html += `<tr${rowBg}>`\n for (let j = 0; j < columns.length; j++) {\n const cellBorder = bordered ? 'border:1px solid #ddd;' : ''\n const col = columns[j]\n const alignStyle = col?.align ? `text-align:${col.align};` : ''\n html += `<td style=\"${cellBorder}${alignStyle}padding:8px\">${escapeHtml(String(rows[i]?.[j] ?? ''))}</td>`\n }\n html += '</tr>'\n }\n html += '</tbody></table>'\n return html\n }\n\n case 'list': {\n const tag = p.ordered ? 'ol' : 'ul'\n return `<${tag}>${renderChildren(node.children)}</${tag}>`\n }\n\n case 'list-item':\n return `<li>${renderChildren(node.children)}</li>`\n\n case 'code':\n return `<pre style=\"background:#f5f5f5;padding:12px;border-radius:4px;overflow-x:auto\"><code>${escapeHtml(renderChildren(node.children))}</code></pre>`\n\n case 'divider': {\n const color = (p.color as string) ?? '#ddd'\n const thickness = (p.thickness as number) ?? 1\n return `<hr style=\"border:none;border-top:${thickness}px solid ${color};margin:16px 0\" />`\n }\n\n case 'page-break':\n return '<div style=\"page-break-after:always;break-after:page\"></div>'\n\n case 'spacer':\n return `<div style=\"height:${p.height}px\"></div>`\n\n case 'button': {\n const bg = (p.background as string) ?? '#4f46e5'\n const color = (p.color as string) ?? '#fff'\n const radius = (p.borderRadius as number) ?? 4\n const pad = padStr((p.padding ?? [12, 24]) as [number, number])\n const align = (p.align as string) ?? 'left'\n return `<div style=\"text-align:${align}\"><a href=\"${escapeHtml(p.href as string)}\" style=\"display:inline-block;background:${bg};color:${color};padding:${pad};border-radius:${radius}px;text-decoration:none;font-weight:bold\">${renderChildren(node.children)}</a></div>`\n }\n\n case 'quote': {\n const borderColor = (p.borderColor as string) ?? '#ddd'\n return `<blockquote style=\"margin:0;padding:12px 20px;border-left:4px solid ${borderColor};color:#555\">${renderChildren(node.children)}</blockquote>`\n }\n\n default:\n return renderChildren(node.children)\n }\n}\n\ntype PageMargin = number | [number, number] | [number, number, number, number]\n\nexport const htmlRenderer: DocumentRenderer = {\n async render(node: DocNode, options?: RenderOptions): Promise<string> {\n let html = renderNode(node)\n if (options?.direction === 'rtl') {\n html = html.replace('<body>', '<body dir=\"rtl\" style=\"direction:rtl\">')\n }\n return html\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"markdown-BYC_3C9i.js","names":[],"sources":["../src/renderers/markdown.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction renderChild(child: DocChild): string {\n if (typeof child === 'string') return child\n return renderNode(child)\n}\n\nfunction renderChildren(children: DocChild[]): string {\n return children.map(renderChild).join('')\n}\n\nfunction renderInline(children: DocChild[]): string {\n return children.map(renderChild).join('')\n}\n\nfunction renderNode(node: DocNode): string {\n const p = node.props\n\n switch (node.type) {\n case 'document':\n return renderChildren(node.children)\n\n case 'page':\n return renderChildren(node.children)\n\n case 'section':\n return `${renderChildren(node.children)}\\n`\n\n case 'row':\n case 'column':\n return renderChildren(node.children)\n\n case 'heading': {\n const level = (p.level as number) ?? 1\n const prefix = '#'.repeat(Math.min(Math.max(level, 1), 6))\n return `${prefix} ${renderInline(node.children)}\\n\\n`\n }\n\n case 'text': {\n let text = renderInline(node.children)\n if (p.bold) text = `**${text}**`\n if (p.italic) text = `*${text}*`\n if (p.strikethrough) text = `~~${text}~~`\n return `${text}\\n\\n`\n }\n\n case 'link':\n return `[${renderInline(node.children)}](${p.href})`\n\n case 'image': {\n const alt = (p.alt as string) ?? ''\n let md = `![${alt}](${p.src})`\n if (p.caption) md += `\\n*${p.caption}*`\n return `${md}\\n\\n`\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n\n if (columns.length === 0) return ''\n\n // Header\n const header = `| ${columns.map((c) => c.header).join(' | ')} |`\n\n // Separator with alignment\n const separator = `| ${columns\n .map((c) => {\n const align = c.align ?? 'left'\n if (align === 'center') return ':---:'\n if (align === 'right') return '---:'\n return '---'\n })\n .join(' | ')} |`\n\n // Rows\n const body = rows\n .map(\n (row) => `| ${row.map((cell) => String(cell ?? '')).join(' | ')} |`,\n )\n .join('\\n')\n\n let md = `${header}\\n${separator}\\n${body}\\n\\n`\n if (p.caption) md = `*${p.caption}*\\n\\n${md}`\n return md\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n return `${node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item, i) => {\n const prefix = ordered ? `${i + 1}.` : '-'\n return `${prefix} ${renderInline(item.children)}`\n })\n .join('\\n')}\\n\\n`\n }\n\n case 'list-item':\n return renderInline(node.children)\n\n case 'code': {\n const lang = (p.language as string) ?? ''\n const content = renderInline(node.children)\n return `\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\`\\n\\n`\n }\n\n case 'divider':\n return '---\\n\\n'\n\n case 'page-break':\n return '---\\n\\n'\n\n case 'spacer':\n return '\\n'\n\n case 'button':\n return `[${renderInline(node.children)}](${p.href})\\n\\n`\n\n case 'quote':\n return `> ${renderInline(node.children)}\\n\\n`\n\n default:\n return renderChildren(node.children)\n }\n}\n\nexport const markdownRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n return `${renderNode(node).trim()}\\n`\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"notion-DHaQHO6P.js","names":[],"sources":["../src/renderers/notion.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * Notion renderer — outputs Notion Block JSON for the Notion API.\n * Blocks can be appended to a page via `notion.blocks.children.append()`.\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\ninterface RichText {\n type: 'text'\n text: { content: string; link?: { url: string } }\n annotations?: {\n bold?: boolean\n italic?: boolean\n strikethrough?: boolean\n underline?: boolean\n code?: boolean\n }\n}\n\nfunction textToRichText(\n text: string,\n annotations?: RichText['annotations'],\n): RichText[] {\n return [\n {\n type: 'text',\n text: { content: text },\n ...(annotations ? { annotations } : {}),\n },\n ]\n}\n\ninterface NotionBlock {\n object: 'block'\n type: string\n [key: string]: unknown\n}\n\nfunction nodeToBlocks(node: DocNode): NotionBlock[] {\n const p = node.props\n const blocks: NotionBlock[] = []\n\n switch (node.type) {\n case 'document':\n case 'page':\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n blocks.push(...nodeToBlocks(child))\n }\n }\n break\n\n case 'heading': {\n const level = (p.level as number) ?? 1\n const text = getTextContent(node.children)\n const type =\n level <= 1 ? 'heading_1' : level === 2 ? 'heading_2' : 'heading_3'\n blocks.push({\n object: 'block',\n type,\n [type]: { rich_text: textToRichText(text) },\n })\n break\n }\n\n case 'text': {\n const text = getTextContent(node.children)\n const annotations: RichText['annotations'] = {}\n if (p.bold) annotations.bold = true\n if (p.italic) annotations.italic = true\n if (p.strikethrough) annotations.strikethrough = true\n if (p.underline) annotations.underline = true\n blocks.push({\n object: 'block',\n type: 'paragraph',\n paragraph: {\n rich_text: textToRichText(\n text,\n Object.keys(annotations).length > 0 ? annotations : undefined,\n ),\n },\n })\n break\n }\n\n case 'link': {\n const href = p.href as string\n const text = getTextContent(node.children)\n blocks.push({\n object: 'block',\n type: 'paragraph',\n paragraph: {\n rich_text: [\n { type: 'text', text: { content: text, link: { url: href } } },\n ],\n },\n })\n break\n }\n\n case 'image': {\n const src = p.src as string\n if (src.startsWith('http')) {\n blocks.push({\n object: 'block',\n type: 'image',\n image: {\n type: 'external',\n external: { url: src },\n ...(p.caption\n ? { caption: textToRichText(p.caption as string) }\n : {}),\n },\n })\n }\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n\n const tableRows: NotionBlock[] = []\n\n // Header row\n tableRows.push({\n object: 'block',\n type: 'table_row',\n table_row: {\n cells: columns.map((col) =>\n textToRichText(col.header, { bold: true }),\n ),\n },\n })\n\n // Data rows\n for (const row of rows) {\n tableRows.push({\n object: 'block',\n type: 'table_row',\n table_row: {\n cells: columns.map((_, i) => textToRichText(String(row[i] ?? ''))),\n },\n })\n }\n\n blocks.push({\n object: 'block',\n type: 'table',\n table: {\n table_width: columns.length,\n has_column_header: true,\n children: tableRows,\n },\n })\n break\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n const items = node.children.filter(\n (c): c is DocNode => typeof c !== 'string',\n )\n for (const item of items) {\n const text = getTextContent(item.children)\n const type = ordered ? 'numbered_list_item' : 'bulleted_list_item'\n blocks.push({\n object: 'block',\n type,\n [type]: { rich_text: textToRichText(text) },\n })\n }\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n const lang = (p.language as string) ?? 'plain text'\n blocks.push({\n object: 'block',\n type: 'code',\n code: {\n rich_text: textToRichText(text),\n language: lang,\n },\n })\n break\n }\n\n case 'divider':\n case 'page-break':\n blocks.push({ object: 'block', type: 'divider', divider: {} })\n break\n\n case 'spacer':\n blocks.push({\n object: 'block',\n type: 'paragraph',\n paragraph: { rich_text: [] },\n })\n break\n\n case 'button': {\n const href = p.href as string\n const text = getTextContent(node.children)\n blocks.push({\n object: 'block',\n type: 'paragraph',\n paragraph: {\n rich_text: [\n {\n type: 'text',\n text: { content: text, link: { url: href } },\n annotations: { bold: true },\n },\n ],\n },\n })\n break\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n blocks.push({\n object: 'block',\n type: 'quote',\n quote: { rich_text: textToRichText(text) },\n })\n break\n }\n }\n\n return blocks\n}\n\nexport const notionRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n const blocks = nodeToBlocks(node)\n return JSON.stringify({ children: blocks }, null, 2)\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pptx-DKQU6bjq.js","names":[],"sources":["../src/renderers/pptx.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * PPTX renderer — lazy-loads pptxgenjs on first use.\n * Each `<Page>` becomes a slide. Document nodes map to PPTX elements.\n *\n * @example\n * ```ts\n * import { render, Document, Page, Heading, Text } from '@pyreon/document'\n *\n * const doc = Document({\n * title: 'Presentation',\n * children: [\n * Page({ children: [Heading({ children: 'Slide 1' }), Text({ children: 'Hello' })] }),\n * Page({ children: [Heading({ children: 'Slide 2' })] }),\n * ],\n * })\n * const pptx = await render(doc, 'pptx') // → Uint8Array\n * ```\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\n/** Vertical position tracker for placing elements on a slide. */\ninterface SlideContext {\n slide: PptxSlide\n y: number\n}\n\n// Duck-typed pptxgenjs interfaces to avoid hard dependency on types\ninterface PptxSlide {\n addText(text: string | PptxTextProps[], opts?: Record<string, unknown>): void\n addImage(opts: Record<string, unknown>): void\n addTable(rows: unknown[][], opts?: Record<string, unknown>): void\n}\n\ninterface PptxTextProps {\n text: string\n options?: Record<string, unknown>\n}\n\ninterface PptxGen {\n addSlide(): PptxSlide\n write(outputType: string): Promise<unknown>\n title: string\n author: string\n subject: string\n}\n\nconst HEADING_SIZES: Record<number, number> = {\n 1: 28,\n 2: 24,\n 3: 20,\n 4: 18,\n 5: 16,\n 6: 14,\n}\n\nconst SLIDE_WIDTH = 10 // inches\nconst CONTENT_MARGIN = 0.5\nconst CONTENT_WIDTH = SLIDE_WIDTH - CONTENT_MARGIN * 2\n\nfunction processNode(node: DocNode, ctx: SlideContext): void {\n const p = node.props\n\n switch (node.type) {\n case 'heading': {\n const level = (p.level as number) ?? 1\n const fontSize = HEADING_SIZES[level] ?? 20\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.6,\n fontSize,\n bold: true,\n color: ((p.color as string) ?? '#000000').replace('#', ''),\n align: (p.align as string) ?? 'left',\n })\n ctx.y += 0.7\n break\n }\n\n case 'text': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.4,\n fontSize: (p.size as number) ?? 14,\n bold: p.bold ?? false,\n italic: p.italic ?? false,\n underline: p.underline ? { style: 'sng' } : undefined,\n strike: p.strikethrough ? 'sngStrike' : undefined,\n color: ((p.color as string) ?? '#333333').replace('#', ''),\n align: (p.align as string) ?? 'left',\n })\n ctx.y += 0.5\n break\n }\n\n case 'image': {\n const src = p.src as string\n const w = Math.min(((p.width as number) ?? 400) / 96, CONTENT_WIDTH)\n const h = ((p.height as number) ?? 300) / 96\n\n if (src.startsWith('data:')) {\n ctx.slide.addImage({\n data: src,\n x: CONTENT_MARGIN,\n y: ctx.y,\n w,\n h,\n })\n ctx.y += h + 0.2\n }\n // HTTP URLs and local paths are not supported — skip silently\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n const hs = p.headerStyle as\n | { background?: string; color?: string }\n | undefined\n\n const headerRow = columns.map((col) => ({\n text: col.header,\n options: {\n bold: true,\n fill: { color: (hs?.background ?? '#f5f5f5').replace('#', '') },\n color: (hs?.color ?? '#000000').replace('#', ''),\n align: col.align ?? 'left',\n fontSize: 12,\n },\n }))\n\n const dataRows = rows.map((row, rowIdx) =>\n columns.map((col, colIdx) => ({\n text: String(row[colIdx] ?? ''),\n options: {\n align: col.align ?? 'left',\n fontSize: 11,\n fill:\n p.striped && rowIdx % 2 === 1 ? { color: 'F9F9F9' } : undefined,\n },\n })),\n )\n\n const allRows = [headerRow, ...dataRows]\n const rowHeight = 0.35\n const tableHeight = allRows.length * rowHeight\n\n ctx.slide.addTable(allRows, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n border: { pt: 0.5, color: 'DDDDDD' },\n rowH: rowHeight,\n })\n ctx.y += tableHeight + 0.2\n break\n }\n\n case 'list': {\n const items = node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item) => getTextContent(item.children))\n\n const isOrdered = p.ordered as boolean\n const listText = items.map((item, i) => ({\n text: isOrdered ? `${i + 1}. ${item}\\n` : `\\u2022 ${item}\\n`,\n options: { fontSize: 13, bullet: false },\n }))\n\n ctx.slide.addText(listText, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: items.length * 0.35,\n })\n ctx.y += items.length * 0.35 + 0.1\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.5,\n fontSize: 10,\n fontFace: 'Courier New',\n fill: { color: 'F5F5F5' },\n color: '333333',\n })\n ctx.y += 0.6\n break\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN + 0.3,\n y: ctx.y,\n w: CONTENT_WIDTH - 0.3,\n h: 0.5,\n fontSize: 13,\n italic: true,\n color: '555555',\n })\n ctx.y += 0.6\n break\n }\n\n case 'link': {\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.4,\n fontSize: 13,\n color: '4F46E5',\n underline: { style: 'sng' },\n hyperlink: { url: p.href as string },\n })\n ctx.y += 0.5\n break\n }\n\n case 'button': {\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: 3,\n h: 0.5,\n fontSize: 14,\n bold: true,\n color: ((p.color as string) ?? '#ffffff').replace('#', ''),\n fill: {\n color: ((p.background as string) ?? '#4f46e5').replace('#', ''),\n },\n align: 'center',\n hyperlink: { url: p.href as string },\n })\n ctx.y += 0.6\n break\n }\n\n case 'spacer': {\n ctx.y += ((p.height as number) ?? 12) / 72\n break\n }\n\n case 'divider': {\n // Render as a thin line using a text element with top border\n ctx.slide.addText('', {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.02,\n fill: { color: ((p.color as string) ?? '#DDDDDD').replace('#', '') },\n })\n ctx.y += 0.2\n break\n }\n\n // Container types — recurse into children\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n processNode(child, ctx)\n }\n }\n break\n\n default:\n break\n }\n}\n\nfunction processSlide(pageNode: DocNode, pptx: PptxGen): void {\n const slide = pptx.addSlide()\n const ctx: SlideContext = { slide, y: CONTENT_MARGIN }\n\n for (const child of pageNode.children) {\n if (typeof child !== 'string') {\n processNode(child, ctx)\n }\n }\n}\n\nexport const pptxRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<Uint8Array> {\n const PptxGenJS = await import('pptxgenjs')\n const PptxGenClass = PptxGenJS.default ?? PptxGenJS\n\n const pptx = new PptxGenClass() as PptxGen\n\n // Set metadata\n if (node.props.title) pptx.title = node.props.title as string\n if (node.props.author) pptx.author = node.props.author as string\n if (node.props.subject) pptx.subject = node.props.subject as string\n\n // Collect pages — each becomes a slide\n const pages: DocNode[] = []\n for (const child of node.children) {\n if (typeof child !== 'string' && child.type === 'page') {\n pages.push(child)\n }\n }\n\n // If no explicit pages, treat entire document content as one slide\n if (pages.length === 0) {\n const syntheticPage: DocNode = {\n type: 'page',\n props: {},\n children: node.children,\n }\n pages.push(syntheticPage)\n }\n\n for (const page of pages) {\n processSlide(page, pptx)\n }\n\n const output = await pptx.write('arraybuffer')\n return new Uint8Array(output as ArrayBuffer)\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"slack-CJRJgkag.js","names":[],"sources":["../src/renderers/slack.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * Slack Block Kit renderer — outputs JSON that can be posted via Slack's API.\n * Maps document nodes to Slack blocks (section, header, divider, image, etc.).\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\ninterface SlackBlock {\n type: string\n [key: string]: unknown\n}\n\nfunction mrkdwn(text: string): { type: 'mrkdwn'; text: string } {\n return { type: 'mrkdwn', text }\n}\n\nfunction plainText(text: string): { type: 'plain_text'; text: string } {\n return { type: 'plain_text', text }\n}\n\nfunction nodeToBlocks(node: DocNode): SlackBlock[] {\n const p = node.props\n const blocks: SlackBlock[] = []\n\n switch (node.type) {\n case 'document':\n case 'page':\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n blocks.push(...nodeToBlocks(child))\n }\n }\n break\n\n case 'heading':\n blocks.push({\n type: 'header',\n text: plainText(getTextContent(node.children)),\n })\n break\n\n case 'text': {\n let text = getTextContent(node.children)\n if (p.bold) text = `*${text}*`\n if (p.italic) text = `_${text}_`\n if (p.strikethrough) text = `~${text}~`\n blocks.push({\n type: 'section',\n text: mrkdwn(text),\n })\n break\n }\n\n case 'link': {\n const href = p.href as string\n const text = getTextContent(node.children)\n blocks.push({\n type: 'section',\n text: mrkdwn(`<${href}|${text}>`),\n })\n break\n }\n\n case 'image': {\n const src = p.src as string\n // Slack only supports public URLs for images\n if (src.startsWith('http')) {\n blocks.push({\n type: 'image',\n image_url: src,\n alt_text: (p.alt as string) ?? 'Image',\n ...(p.caption ? { title: plainText(p.caption as string) } : {}),\n })\n }\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n\n // Slack doesn't have native tables — render as formatted text\n const header = columns.map((c) => `*${c.header}*`).join(' | ')\n const separator = columns.map(() => '---').join(' | ')\n const body = rows\n .map((row) => row.map((cell) => String(cell ?? '')).join(' | '))\n .join('\\n')\n\n let text = `${header}\\n${separator}\\n${body}`\n if (p.caption) text = `_${p.caption}_\\n${text}`\n\n blocks.push({\n type: 'section',\n text: mrkdwn(`\\`\\`\\`\\n${text}\\n\\`\\`\\``),\n })\n break\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n const items = node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item, i) => {\n const prefix = ordered ? `${i + 1}.` : '•'\n return `${prefix} ${getTextContent(item.children)}`\n })\n .join('\\n')\n blocks.push({\n type: 'section',\n text: mrkdwn(items),\n })\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n const lang = (p.language as string) ?? ''\n blocks.push({\n type: 'section',\n text: mrkdwn(`\\`\\`\\`${lang}\\n${text}\\n\\`\\`\\``),\n })\n break\n }\n\n case 'divider':\n case 'page-break':\n blocks.push({ type: 'divider' })\n break\n\n case 'spacer':\n // No equivalent in Slack — skip\n break\n\n case 'button': {\n const href = p.href as string\n const text = getTextContent(node.children)\n blocks.push({\n type: 'actions',\n elements: [\n {\n type: 'button',\n text: plainText(text),\n url: href,\n style: 'primary',\n },\n ],\n })\n break\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n blocks.push({\n type: 'section',\n text: mrkdwn(`> ${text}`),\n })\n break\n }\n }\n\n return blocks\n}\n\nexport const slackRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n const blocks = nodeToBlocks(node)\n return JSON.stringify({ blocks }, null, 2)\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"svg-BM8biZmL.js","names":[],"sources":["../src/renderers/svg.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * SVG renderer — generates a standalone SVG document from the node tree.\n * Useful for thumbnails, social cards, and preview images.\n * No external dependencies — pure SVG string generation.\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\ninterface RenderContext {\n y: number\n width: number\n padding: number\n}\n\nfunction renderNode(node: DocNode, ctx: RenderContext): string {\n const p = node.props\n const contentWidth = ctx.width - ctx.padding * 2\n let svg = ''\n\n switch (node.type) {\n case 'document':\n case 'page':\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n svg += renderNode(child, ctx)\n }\n }\n break\n\n case 'heading': {\n const level = (p.level as number) ?? 1\n const sizes: Record<number, number> = {\n 1: 28,\n 2: 24,\n 3: 20,\n 4: 18,\n 5: 16,\n 6: 14,\n }\n const size = sizes[level] ?? 24\n const color = (p.color as string) ?? '#000000'\n const text = escapeXml(getTextContent(node.children))\n ctx.y += size + 8\n 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>`\n ctx.y += 12\n break\n }\n\n case 'text': {\n const size = (p.size as number) ?? 14\n const color = (p.color as string) ?? '#333333'\n const weight = p.bold ? 'bold' : 'normal'\n const style = p.italic ? 'italic' : 'normal'\n const text = escapeXml(getTextContent(node.children))\n ctx.y += size + 4\n 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>`\n ctx.y += 10\n break\n }\n\n case 'link': {\n const href = p.href as string\n const text = escapeXml(getTextContent(node.children))\n const color = (p.color as string) ?? '#4f46e5'\n ctx.y += 18\n 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>`\n ctx.y += 10\n break\n }\n\n case 'image': {\n const width = (p.width as number) ?? Math.min(contentWidth, 400)\n const height = (p.height as number) ?? 200\n const src = p.src as string\n\n if (src.startsWith('data:') || src.startsWith('http')) {\n svg += `<image x=\"${ctx.padding}\" y=\"${ctx.y}\" width=\"${width}\" height=\"${height}\" href=\"${escapeXml(src)}\" />`\n } else {\n // Placeholder rectangle for local paths\n svg += `<rect x=\"${ctx.padding}\" y=\"${ctx.y}\" width=\"${width}\" height=\"${height}\" fill=\"#f0f0f0\" stroke=\"#ddd\" rx=\"4\" />`\n 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>`\n }\n ctx.y += height + 8\n\n if (p.caption) {\n ctx.y += 14\n svg += `<text x=\"${ctx.padding}\" y=\"${ctx.y}\" font-size=\"12\" fill=\"#666\" font-style=\"italic\" font-family=\"system-ui, sans-serif\">${escapeXml(p.caption as string)}</text>`\n ctx.y += 8\n }\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n const hs = p.headerStyle as\n | { background?: string; color?: string }\n | undefined\n const striped = p.striped as boolean | undefined\n\n const colWidth = contentWidth / columns.length\n const rowHeight = 28\n const headerBg = hs?.background ?? '#f5f5f5'\n const headerColor = hs?.color ?? '#000000'\n\n // Header\n svg += `<rect x=\"${ctx.padding}\" y=\"${ctx.y}\" width=\"${contentWidth}\" height=\"${rowHeight}\" fill=\"${headerBg}\" />`\n for (let i = 0; i < columns.length; i++) {\n const col = columns[i]\n if (!col) continue\n svg += `<text x=\"${ctx.padding + i * colWidth + 8}\" y=\"${ctx.y + 18}\" font-size=\"12\" font-weight=\"bold\" fill=\"${headerColor}\" font-family=\"system-ui, sans-serif\">${escapeXml(col.header)}</text>`\n }\n ctx.y += rowHeight\n\n // Rows\n for (let r = 0; r < rows.length; r++) {\n if (striped && r % 2 === 1) {\n svg += `<rect x=\"${ctx.padding}\" y=\"${ctx.y}\" width=\"${contentWidth}\" height=\"${rowHeight}\" fill=\"#f9f9f9\" />`\n }\n for (let c = 0; c < columns.length; c++) {\n 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>`\n }\n ctx.y += rowHeight\n }\n\n // Bottom border\n svg += `<line x1=\"${ctx.padding}\" y1=\"${ctx.y}\" x2=\"${ctx.padding + contentWidth}\" y2=\"${ctx.y}\" stroke=\"#ddd\" stroke-width=\"1\" />`\n ctx.y += 12\n break\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n const items = node.children.filter(\n (c): c is DocNode => typeof c !== 'string',\n )\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n if (!item) continue\n const prefix = ordered ? `${i + 1}.` : '•'\n const text = escapeXml(getTextContent(item.children))\n ctx.y += 18\n svg += `<text x=\"${ctx.padding + 16}\" y=\"${ctx.y}\" font-size=\"13\" fill=\"#333\" font-family=\"system-ui, sans-serif\">${prefix} ${text}</text>`\n }\n ctx.y += 10\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n const lines = text.split('\\n')\n const codeHeight = lines.length * 18 + 16\n svg += `<rect x=\"${ctx.padding}\" y=\"${ctx.y}\" width=\"${contentWidth}\" height=\"${codeHeight}\" fill=\"#f5f5f5\" rx=\"4\" />`\n for (let i = 0; i < lines.length; i++) {\n svg += `<text x=\"${ctx.padding + 12}\" y=\"${ctx.y + 20 + i * 18}\" font-size=\"12\" fill=\"#333\" font-family=\"monospace\">${escapeXml(lines[i] ?? '')}</text>`\n }\n ctx.y += codeHeight + 8\n break\n }\n\n case 'divider': {\n const color = (p.color as string) ?? '#ddd'\n const thickness = (p.thickness as number) ?? 1\n ctx.y += 12\n svg += `<line x1=\"${ctx.padding}\" y1=\"${ctx.y}\" x2=\"${ctx.padding + contentWidth}\" y2=\"${ctx.y}\" stroke=\"${color}\" stroke-width=\"${thickness}\" />`\n ctx.y += 12\n break\n }\n\n case 'page-break':\n ctx.y += 16\n svg += `<line x1=\"${ctx.padding}\" y1=\"${ctx.y}\" x2=\"${ctx.padding + contentWidth}\" y2=\"${ctx.y}\" stroke=\"#ccc\" stroke-width=\"2\" stroke-dasharray=\"8,4\" />`\n ctx.y += 16\n break\n\n case 'spacer':\n ctx.y += (p.height as number) ?? 12\n break\n\n case 'button': {\n const bg = (p.background as string) ?? '#4f46e5'\n const color = (p.color as string) ?? '#ffffff'\n const text = escapeXml(getTextContent(node.children))\n const btnWidth = Math.min(text.length * 10 + 48, contentWidth)\n const btnHeight = 40\n ctx.y += 8\n svg += `<rect x=\"${ctx.padding}\" y=\"${ctx.y}\" width=\"${btnWidth}\" height=\"${btnHeight}\" fill=\"${bg}\" rx=\"4\" />`\n svg += `<text x=\"${ctx.padding + btnWidth / 2}\" y=\"${ctx.y + 25}\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"bold\" fill=\"${color}\" font-family=\"system-ui, sans-serif\">${text}</text>`\n ctx.y += btnHeight + 12\n break\n }\n\n case 'quote': {\n const borderColor = (p.borderColor as string) ?? '#ddd'\n const text = escapeXml(getTextContent(node.children))\n ctx.y += 4\n svg += `<rect x=\"${ctx.padding}\" y=\"${ctx.y}\" width=\"4\" height=\"20\" fill=\"${borderColor}\" />`\n svg += `<text x=\"${ctx.padding + 16}\" y=\"${ctx.y + 15}\" font-size=\"13\" fill=\"#555\" font-style=\"italic\" font-family=\"system-ui, sans-serif\">${text}</text>`\n ctx.y += 28\n break\n }\n }\n\n return svg\n}\n\nexport const svgRenderer: DocumentRenderer = {\n async render(node: DocNode, options?: RenderOptions): Promise<string> {\n const width = 800\n const padding = 40\n const ctx: RenderContext = { y: padding, width, padding }\n\n const content = renderNode(node, ctx)\n const height = ctx.y + padding\n\n const dir = options?.direction === 'rtl' ? ' direction=\"rtl\"' : ''\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\"${dir}>\n<rect width=\"${width}\" height=\"${height}\" fill=\"#ffffff\" />\n${content}\n</svg>`\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"teams-S99tonRG.js","names":[],"sources":["../src/renderers/teams.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * Microsoft Teams renderer — outputs Adaptive Cards JSON.\n * Can be posted via Teams Webhooks, Bot Framework, or Power Automate.\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\ninterface AdaptiveElement {\n type: string\n [key: string]: unknown\n}\n\nfunction nodeToElements(node: DocNode): AdaptiveElement[] {\n const p = node.props\n const elements: AdaptiveElement[] = []\n\n switch (node.type) {\n case 'document':\n case 'page':\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n elements.push(...nodeToElements(child))\n }\n }\n break\n\n case 'heading': {\n const level = (p.level as number) ?? 1\n const sizeMap: Record<number, string> = {\n 1: 'extraLarge',\n 2: 'large',\n 3: 'medium',\n 4: 'default',\n 5: 'small',\n 6: 'small',\n }\n elements.push({\n type: 'TextBlock',\n text: getTextContent(node.children),\n size: sizeMap[level] ?? 'large',\n weight: 'bolder',\n wrap: true,\n })\n break\n }\n\n case 'text': {\n let text = getTextContent(node.children)\n if (p.bold) text = `**${text}**`\n if (p.italic) text = `_${text}_`\n if (p.strikethrough) text = `~~${text}~~`\n elements.push({\n type: 'TextBlock',\n text,\n wrap: true,\n ...(p.color ? { color: 'default' } : {}),\n ...(p.size\n ? { size: (p.size as number) >= 18 ? 'large' : 'default' }\n : {}),\n })\n break\n }\n\n case 'link': {\n const href = p.href as string\n const text = getTextContent(node.children)\n elements.push({\n type: 'TextBlock',\n text: `[${text}](${href})`,\n wrap: true,\n })\n break\n }\n\n case 'image': {\n const src = p.src as string\n if (src.startsWith('http')) {\n elements.push({\n type: 'Image',\n url: src,\n altText: (p.alt as string) ?? 'Image',\n size: 'large',\n })\n }\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n\n // Adaptive Cards have native Table support (schema 1.5+)\n const tableColumns = columns.map((col) => ({\n type: 'Column',\n width: 'stretch',\n items: [\n {\n type: 'TextBlock',\n text: `**${col.header}**`,\n weight: 'bolder',\n wrap: true,\n },\n ...rows.map((row, i) => ({\n type: 'TextBlock',\n text: String(row[columns.indexOf(col)] ?? ''),\n wrap: true,\n separator: i === 0,\n })),\n ],\n }))\n\n elements.push({\n type: 'ColumnSet',\n columns: tableColumns,\n })\n break\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n const items = node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item, i) => {\n const prefix = ordered ? `${i + 1}.` : '•'\n return `${prefix} ${getTextContent(item.children)}`\n })\n .join('\\n')\n elements.push({\n type: 'TextBlock',\n text: items,\n wrap: true,\n })\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n elements.push({\n type: 'TextBlock',\n text: `\\`\\`\\`\\n${text}\\n\\`\\`\\``,\n fontType: 'monospace',\n wrap: true,\n })\n break\n }\n\n case 'divider':\n case 'page-break':\n elements.push({\n type: 'TextBlock',\n text: ' ',\n separator: true,\n })\n break\n\n case 'spacer':\n elements.push({\n type: 'TextBlock',\n text: ' ',\n spacing: 'large',\n })\n break\n\n case 'button': {\n elements.push({\n type: 'ActionSet',\n actions: [\n {\n type: 'Action.OpenUrl',\n title: getTextContent(node.children),\n url: p.href as string,\n style: 'positive',\n },\n ],\n })\n break\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n elements.push({\n type: 'Container',\n style: 'emphasis',\n items: [\n {\n type: 'TextBlock',\n text: `_${text}_`,\n wrap: true,\n isSubtle: true,\n },\n ],\n })\n break\n }\n }\n\n return elements\n}\n\nexport const teamsRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n const body = nodeToElements(node)\n const card = {\n type: 'AdaptiveCard',\n $schema: 'http://adaptivecards.io/schemas/adaptive-card.json',\n version: '1.5',\n body,\n }\n return JSON.stringify(card, null, 2)\n },\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"telegram-CbEO_2PN.js","names":[],"sources":["../src/renderers/telegram.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * Telegram renderer — outputs HTML using Telegram's supported subset.\n * Telegram Bot API supports: <b>, <i>, <u>, <s>, <a>, <code>, <pre>, <blockquote>.\n * No tables, no images inline — images sent separately via sendPhoto.\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction esc(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\nfunction renderNode(node: DocNode): string {\n const p = node.props\n\n switch (node.type) {\n case 'document':\n case 'page':\n case 'section':\n case 'row':\n case 'column':\n return node.children\n .map((c) => (typeof c === 'string' ? esc(c) : renderNode(c)))\n .join('')\n\n case 'heading': {\n const text = esc(getTextContent(node.children))\n return `<b>${text}</b>\\n\\n`\n }\n\n case 'text': {\n let text = esc(getTextContent(node.children))\n if (p.bold) text = `<b>${text}</b>`\n if (p.italic) text = `<i>${text}</i>`\n if (p.underline) text = `<u>${text}</u>`\n if (p.strikethrough) text = `<s>${text}</s>`\n return `${text}\\n\\n`\n }\n\n case 'link': {\n const href = p.href as string\n const text = esc(getTextContent(node.children))\n return `<a href=\"${esc(href)}\">${text}</a>\\n\\n`\n }\n\n case 'image':\n // Telegram doesn't support inline images in HTML\n // Images need to be sent separately via sendPhoto\n return ''\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n\n // Render as preformatted text since Telegram has no table support\n const header = columns.map((c) => c.header).join(' | ')\n const separator = columns.map(() => '---').join('-+-')\n const body = rows\n .map((row) => row.map((c) => String(c ?? '')).join(' | '))\n .join('\\n')\n\n return `<pre>${esc(header)}\\n${esc(separator)}\\n${esc(body)}</pre>\\n\\n`\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n const items = node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item, i) => {\n const prefix = ordered ? `${i + 1}.` : '•'\n return `${prefix} ${esc(getTextContent(item.children))}`\n })\n .join('\\n')\n return `${items}\\n\\n`\n }\n\n case 'code': {\n const lang = (p.language as string) ?? ''\n const text = esc(getTextContent(node.children))\n if (lang) {\n return `<pre><code class=\"language-${esc(lang)}\">${text}</code></pre>\\n\\n`\n }\n return `<pre>${text}</pre>\\n\\n`\n }\n\n case 'divider':\n case 'page-break':\n return '───────────\\n\\n'\n\n case 'spacer':\n return '\\n'\n\n case 'button': {\n const href = p.href as string\n const text = esc(getTextContent(node.children))\n return `<a href=\"${esc(href)}\">${text}</a>\\n\\n`\n }\n\n case 'quote': {\n const text = esc(getTextContent(node.children))\n return `<blockquote>${text}</blockquote>\\n\\n`\n }\n\n default:\n return ''\n }\n}\n\nexport const telegramRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n return renderNode(node).trim()\n },\n}\n"],"mappings":";;;;;;AAcA,SAAS,cAAc,KAAwC;AAC7D,QAAO,OAAO,QAAQ,WAAW,EAAE,QAAQ,KAAK,GAAG;;AAGrD,SAAS,IAAI,KAAqB;AAChC,QAAO,IACJ,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,SAAS;;AAG5B,SAAS,eAAe,UAA8B;AACpD,QAAO,SACJ,KAAK,MACJ,OAAO,MAAM,WAAW,IAAI,eAAgB,EAAc,SAAS,CACpE,CACA,KAAK,GAAG;;AAGb,SAAS,WAAW,MAAuB;CACzC,MAAM,IAAI,KAAK;AAEf,SAAQ,KAAK,MAAb;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO,KAAK,SACT,KAAK,MAAO,OAAO,MAAM,WAAW,IAAI,EAAE,GAAG,WAAW,EAAE,CAAE,CAC5D,KAAK,GAAG;EAEb,KAAK,UAEH,QAAO,MADM,IAAI,eAAe,KAAK,SAAS,CAAC,CAC7B;EAGpB,KAAK,QAAQ;GACX,IAAI,OAAO,IAAI,eAAe,KAAK,SAAS,CAAC;AAC7C,OAAI,EAAE,KAAM,QAAO,MAAM,KAAK;AAC9B,OAAI,EAAE,OAAQ,QAAO,MAAM,KAAK;AAChC,OAAI,EAAE,UAAW,QAAO,MAAM,KAAK;AACnC,OAAI,EAAE,cAAe,QAAO,MAAM,KAAK;AACvC,UAAO,GAAG,KAAK;;EAGjB,KAAK,QAAQ;GACX,MAAM,OAAO,EAAE;GACf,MAAM,OAAO,IAAI,eAAe,KAAK,SAAS,CAAC;AAC/C,UAAO,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK;;EAGxC,KAAK,QAGH,QAAO;EAET,KAAK,SAAS;GACZ,MAAM,WAAY,EAAE,WAAW,EAAE,EAA+B,IAC9D,cACD;GACD,MAAM,OAAQ,EAAE,QAAQ,EAAE;GAG1B,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM;GACvD,MAAM,YAAY,QAAQ,UAAU,MAAM,CAAC,KAAK,MAAM;GACtD,MAAM,OAAO,KACV,KAAK,QAAQ,IAAI,KAAK,MAAM,OAAO,KAAK,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CACzD,KAAK,KAAK;AAEb,UAAO,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,IAAI,KAAK,CAAC;;EAG9D,KAAK,QAAQ;GACX,MAAM,UAAU,EAAE;AAQlB,UAAO,GAPO,KAAK,SAChB,QAAQ,MAAoB,OAAO,MAAM,SAAS,CAClD,KAAK,MAAM,MAAM;AAEhB,WAAO,GADQ,UAAU,GAAG,IAAI,EAAE,KAAK,IACtB,GAAG,IAAI,eAAe,KAAK,SAAS,CAAC;KACtD,CACD,KAAK,KAAK,CACG;;EAGlB,KAAK,QAAQ;GACX,MAAM,OAAQ,EAAE,YAAuB;GACvC,MAAM,OAAO,IAAI,eAAe,KAAK,SAAS,CAAC;AAC/C,OAAI,KACF,QAAO,8BAA8B,IAAI,KAAK,CAAC,IAAI,KAAK;AAE1D,UAAO,QAAQ,KAAK;;EAGtB,KAAK;EACL,KAAK,aACH,QAAO;EAET,KAAK,SACH,QAAO;EAET,KAAK,UAAU;GACb,MAAM,OAAO,EAAE;GACf,MAAM,OAAO,IAAI,eAAe,KAAK,SAAS,CAAC;AAC/C,UAAO,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK;;EAGxC,KAAK,QAEH,QAAO,eADM,IAAI,eAAe,KAAK,SAAS,CAAC,CACpB;EAG7B,QACE,QAAO;;;AAIb,MAAa,mBAAqC,EAChD,MAAM,OAAO,MAAe,UAA2C;AACrE,QAAO,WAAW,KAAK,CAAC,MAAM;GAEjC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"whatsapp-DJ2D1jGG.js","names":[],"sources":["../src/renderers/whatsapp.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * WhatsApp renderer — outputs formatted text using WhatsApp's markup.\n * WhatsApp supports: *bold*, _italic_, ~strikethrough~, ```code```, > quote\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) =>\n typeof c === 'string' ? c : getTextContent((c as DocNode).children),\n )\n .join('')\n}\n\nfunction renderNode(node: DocNode): string {\n const p = node.props\n\n switch (node.type) {\n case 'document':\n case 'page':\n case 'section':\n case 'row':\n case 'column':\n return node.children\n .map((c) => (typeof c === 'string' ? c : renderNode(c)))\n .join('')\n\n case 'heading': {\n const text = getTextContent(node.children)\n return `*${text}*\\n\\n`\n }\n\n case 'text': {\n let text = getTextContent(node.children)\n if (p.bold) text = `*${text}*`\n if (p.italic) text = `_${text}_`\n if (p.strikethrough) text = `~${text}~`\n return `${text}\\n\\n`\n }\n\n case 'link': {\n const href = p.href as string\n const text = getTextContent(node.children)\n return `${text}: ${href}\\n\\n`\n }\n\n case 'image':\n // WhatsApp doesn't support inline images in text\n return ''\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(\n resolveColumn,\n )\n const rows = (p.rows ?? []) as (string | number)[][]\n\n const header = columns.map((c) => `*${c.header}*`).join(' | ')\n const body = rows\n .map((row) => row.map((c) => String(c ?? '')).join(' | '))\n .join('\\n')\n\n let result = `${header}\\n${body}\\n\\n`\n if (p.caption) result = `_${p.caption}_\\n${result}`\n return result\n }\n\n case 'list': {\n const ordered = p.ordered as boolean | undefined\n return `${node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item, i) => {\n const prefix = ordered ? `${i + 1}.` : '•'\n return `${prefix} ${getTextContent(item.children)}`\n })\n .join('\\n')}\\n\\n`\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n return `\\`\\`\\`${text}\\`\\`\\`\\n\\n`\n }\n\n case 'divider':\n case 'page-break':\n return '───────────\\n\\n'\n\n case 'spacer':\n return '\\n'\n\n case 'button': {\n const href = p.href as string\n const text = getTextContent(node.children)\n return `*${text}*: ${href}\\n\\n`\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n return `> ${text}\\n\\n`\n }\n\n default:\n return ''\n }\n}\n\nexport const whatsappRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<string> {\n return renderNode(node).trim()\n },\n}\n"],"mappings":";;;;;AAaA,SAAS,cAAc,KAAwC;AAC7D,QAAO,OAAO,QAAQ,WAAW,EAAE,QAAQ,KAAK,GAAG;;AAGrD,SAAS,eAAe,UAA8B;AACpD,QAAO,SACJ,KAAK,MACJ,OAAO,MAAM,WAAW,IAAI,eAAgB,EAAc,SAAS,CACpE,CACA,KAAK,GAAG;;AAGb,SAAS,WAAW,MAAuB;CACzC,MAAM,IAAI,KAAK;AAEf,SAAQ,KAAK,MAAb;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO,KAAK,SACT,KAAK,MAAO,OAAO,MAAM,WAAW,IAAI,WAAW,EAAE,CAAE,CACvD,KAAK,GAAG;EAEb,KAAK,UAEH,QAAO,IADM,eAAe,KAAK,SAAS,CAC1B;EAGlB,KAAK,QAAQ;GACX,IAAI,OAAO,eAAe,KAAK,SAAS;AACxC,OAAI,EAAE,KAAM,QAAO,IAAI,KAAK;AAC5B,OAAI,EAAE,OAAQ,QAAO,IAAI,KAAK;AAC9B,OAAI,EAAE,cAAe,QAAO,IAAI,KAAK;AACrC,UAAO,GAAG,KAAK;;EAGjB,KAAK,QAAQ;GACX,MAAM,OAAO,EAAE;AAEf,UAAO,GADM,eAAe,KAAK,SAAS,CAC3B,IAAI,KAAK;;EAG1B,KAAK,QAEH,QAAO;EAET,KAAK,SAAS;GACZ,MAAM,WAAY,EAAE,WAAW,EAAE,EAA+B,IAC9D,cACD;GACD,MAAM,OAAQ,EAAE,QAAQ,EAAE;GAO1B,IAAI,SAAS,GALE,QAAQ,KAAK,MAAM,IAAI,EAAE,OAAO,GAAG,CAAC,KAAK,MAAM,CAKvC,IAJV,KACV,KAAK,QAAQ,IAAI,KAAK,MAAM,OAAO,KAAK,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CACzD,KAAK,KAAK,CAEmB;AAChC,OAAI,EAAE,QAAS,UAAS,IAAI,EAAE,QAAQ,KAAK;AAC3C,UAAO;;EAGT,KAAK,QAAQ;GACX,MAAM,UAAU,EAAE;AAClB,UAAO,GAAG,KAAK,SACZ,QAAQ,MAAoB,OAAO,MAAM,SAAS,CAClD,KAAK,MAAM,MAAM;AAEhB,WAAO,GADQ,UAAU,GAAG,IAAI,EAAE,KAAK,IACtB,GAAG,eAAe,KAAK,SAAS;KACjD,CACD,KAAK,KAAK,CAAC;;EAGhB,KAAK,OAEH,QAAO,SADM,eAAe,KAAK,SAAS,CACrB;EAGvB,KAAK;EACL,KAAK,aACH,QAAO;EAET,KAAK,SACH,QAAO;EAET,KAAK,UAAU;GACb,MAAM,OAAO,EAAE;AAEf,UAAO,IADM,eAAe,KAAK,SAAS,CAC1B,KAAK,KAAK;;EAG5B,KAAK,QAEH,QAAO,KADM,eAAe,KAAK,SAAS,CACzB;EAGnB,QACE,QAAO;;;AAIb,MAAa,mBAAqC,EAChD,MAAM,OAAO,MAAe,UAA2C;AACrE,QAAO,WAAW,KAAK,CAAC,MAAM;GAEjC"}