@pyreon/document 0.7.0 → 0.9.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 (76) hide show
  1. package/README.md +68 -0
  2. package/lib/analysis/index.js.html +1 -1
  3. package/lib/{confluence-Va8e7RxQ.js → confluence-Bd3ua1Ut.js} +6 -4
  4. package/lib/confluence-Bd3ua1Ut.js.map +1 -0
  5. package/lib/{csv-2c38ub-Y.js → csv-COrS4qdy.js} +1 -1
  6. package/lib/{csv-2c38ub-Y.js.map → csv-COrS4qdy.js.map} +1 -1
  7. package/lib/{discord-DAoUZqvE.js → discord-BLUnkEh9.js} +6 -4
  8. package/lib/discord-BLUnkEh9.js.map +1 -0
  9. package/lib/{docx-CorFwEH9.js → docx-BEBOihjl.js} +27 -26
  10. package/lib/docx-BEBOihjl.js.map +1 -0
  11. package/lib/{email-Bn_Brjdp.js → email-D0bbfWq4.js} +15 -13
  12. package/lib/email-D0bbfWq4.js.map +1 -0
  13. package/lib/{google-chat-B6I017I1.js → google-chat-CkKCBUWC.js} +6 -4
  14. package/lib/google-chat-CkKCBUWC.js.map +1 -0
  15. package/lib/{html-De_iS_f0.js → html-B5biprN2.js} +15 -13
  16. package/lib/html-B5biprN2.js.map +1 -0
  17. package/lib/index.js +44 -42
  18. package/lib/index.js.map +1 -1
  19. package/lib/{markdown-BYC_3C9i.js → markdown-CdtlFGC0.js} +6 -4
  20. package/lib/markdown-CdtlFGC0.js.map +1 -0
  21. package/lib/{notion-DHaQHO6P.js → notion-iG2C5bEY.js} +6 -4
  22. package/lib/notion-iG2C5bEY.js.map +1 -0
  23. package/lib/{pdf-CDPc5Itc.js → pdf-DIUQUEdj.js} +1 -1
  24. package/lib/{pdf-CDPc5Itc.js.map → pdf-DIUQUEdj.js.map} +1 -1
  25. package/lib/{pptx-DKQU6bjq.js → pptx-Dd33oL3_.js} +13 -11
  26. package/lib/pptx-Dd33oL3_.js.map +1 -0
  27. package/lib/sanitize-O_3j1mNJ.js +73 -0
  28. package/lib/sanitize-O_3j1mNJ.js.map +1 -0
  29. package/lib/{slack-CJRJgkag.js → slack-BI3EQwYm.js} +6 -4
  30. package/lib/slack-BI3EQwYm.js.map +1 -0
  31. package/lib/{svg-BM8biZmL.js → svg-BKxumy-p.js} +14 -12
  32. package/lib/svg-BKxumy-p.js.map +1 -0
  33. package/lib/{teams-S99tonRG.js → teams-Cwz9lce0.js} +6 -4
  34. package/lib/teams-Cwz9lce0.js.map +1 -0
  35. package/lib/{telegram-CbEO_2PN.js → telegram-gYFqyMXb.js} +5 -3
  36. package/lib/telegram-gYFqyMXb.js.map +1 -0
  37. package/lib/{text-B5U8ucRr.js → text-l1XNXBOC.js} +1 -1
  38. package/lib/{text-B5U8ucRr.js.map → text-l1XNXBOC.js.map} +1 -1
  39. package/lib/types/index.d.ts.map +1 -1
  40. package/lib/{whatsapp-DJ2D1jGG.js → whatsapp-CjSGoOKx.js} +5 -3
  41. package/lib/whatsapp-CjSGoOKx.js.map +1 -0
  42. package/lib/{xlsx-D47x-gZ5.js → xlsx-Bb5TWyXQ.js} +1 -1
  43. package/lib/{xlsx-D47x-gZ5.js.map → xlsx-Bb5TWyXQ.js.map} +1 -1
  44. package/package.json +3 -3
  45. package/src/builder.ts +6 -6
  46. package/src/download.ts +6 -0
  47. package/src/nodes.ts +5 -0
  48. package/src/renderers/confluence.ts +4 -3
  49. package/src/renderers/discord.ts +4 -3
  50. package/src/renderers/docx.ts +44 -32
  51. package/src/renderers/email.ts +15 -12
  52. package/src/renderers/google-chat.ts +4 -3
  53. package/src/renderers/html.ts +20 -12
  54. package/src/renderers/markdown.ts +4 -3
  55. package/src/renderers/notion.ts +4 -3
  56. package/src/renderers/pptx.ts +11 -10
  57. package/src/renderers/slack.ts +4 -3
  58. package/src/renderers/svg.ts +12 -11
  59. package/src/renderers/teams.ts +4 -3
  60. package/src/renderers/telegram.ts +3 -2
  61. package/src/renderers/whatsapp.ts +3 -2
  62. package/src/sanitize.ts +88 -0
  63. package/lib/confluence-Va8e7RxQ.js.map +0 -1
  64. package/lib/discord-DAoUZqvE.js.map +0 -1
  65. package/lib/docx-CorFwEH9.js.map +0 -1
  66. package/lib/email-Bn_Brjdp.js.map +0 -1
  67. package/lib/google-chat-B6I017I1.js.map +0 -1
  68. package/lib/html-De_iS_f0.js.map +0 -1
  69. package/lib/markdown-BYC_3C9i.js.map +0 -1
  70. package/lib/notion-DHaQHO6P.js.map +0 -1
  71. package/lib/pptx-DKQU6bjq.js.map +0 -1
  72. package/lib/slack-CJRJgkag.js.map +0 -1
  73. package/lib/svg-BM8biZmL.js.map +0 -1
  74. package/lib/teams-S99tonRG.js.map +0 -1
  75. package/lib/telegram-CbEO_2PN.js.map +0 -1
  76. package/lib/whatsapp-DJ2D1jGG.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"text-B5U8ucRr.js","names":[],"sources":["../src/renderers/text.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 pad(\n str: string,\n width: number,\n align: 'left' | 'center' | 'right' = 'left',\n): string {\n if (str.length >= width) return str.slice(0, width)\n const diff = width - str.length\n if (align === 'center') {\n const left = Math.floor(diff / 2)\n return ' '.repeat(left) + str + ' '.repeat(diff - left)\n }\n if (align === 'right') return ' '.repeat(diff) + str\n return str + ' '.repeat(diff)\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 case 'row':\n case 'column':\n return renderChildren(node.children)\n\n case 'heading': {\n const text = renderChildren(node.children)\n const level = (p.level as number) ?? 1\n if (level === 1)\n return `${text.toUpperCase()}\\n${'='.repeat(text.length)}\\n\\n`\n if (level === 2) return `${text}\\n${'-'.repeat(text.length)}\\n\\n`\n return `${text}\\n\\n`\n }\n\n case 'text':\n return `${renderChildren(node.children)}\\n\\n`\n\n case 'link':\n return `${renderChildren(node.children)} (${p.href})`\n\n case 'image': {\n const alt = (p.alt as string) ?? 'Image'\n const caption = p.caption ? ` — ${p.caption}` : ''\n return `[${alt}${caption}]\\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 // Calculate column widths\n const widths = columns.map((col, i) => {\n const headerLen = col.header.length\n const maxDataLen = rows.reduce(\n (max, row) => Math.max(max, String(row[i] ?? '').length),\n 0,\n )\n return Math.max(headerLen, maxDataLen, 3)\n })\n\n // Header\n const header = columns\n .map((col, i) => pad(col.header, widths[i] ?? 3, col.align))\n .join(' | ')\n const separator = widths.map((w) => '-'.repeat(w ?? 3)).join('-+-')\n\n // Rows\n const body = rows\n .map((row) =>\n columns\n .map((col, i) =>\n pad(String(row[i] ?? ''), widths[i] ?? 3, col.align),\n )\n .join(' | '),\n )\n .join('\\n')\n\n let result = `${header}\\n${separator}\\n${body}\\n\\n`\n if (p.caption) result = `${p.caption}\\n\\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} ${renderChildren(item.children)}`\n })\n .join('\\n')}\\n\\n`\n }\n\n case 'list-item':\n return renderChildren(node.children)\n\n case 'code':\n return `${renderChildren(node.children)}\\n\\n`\n\n case 'divider':\n return `${'─'.repeat(40)}\\n\\n`\n\n case 'page-break':\n return `\\n${'═'.repeat(40)}\\n\\n`\n\n case 'spacer':\n return '\\n'\n\n case 'button':\n return `[${renderChildren(node.children)}] → ${p.href}\\n\\n`\n\n case 'quote':\n return ` \"${renderChildren(node.children)}\"\\n\\n`\n\n default:\n return renderChildren(node.children)\n }\n}\n\nexport const textRenderer: 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
+ {"version":3,"file":"text-l1XNXBOC.js","names":[],"sources":["../src/renderers/text.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 pad(\n str: string,\n width: number,\n align: 'left' | 'center' | 'right' = 'left',\n): string {\n if (str.length >= width) return str.slice(0, width)\n const diff = width - str.length\n if (align === 'center') {\n const left = Math.floor(diff / 2)\n return ' '.repeat(left) + str + ' '.repeat(diff - left)\n }\n if (align === 'right') return ' '.repeat(diff) + str\n return str + ' '.repeat(diff)\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 case 'row':\n case 'column':\n return renderChildren(node.children)\n\n case 'heading': {\n const text = renderChildren(node.children)\n const level = (p.level as number) ?? 1\n if (level === 1)\n return `${text.toUpperCase()}\\n${'='.repeat(text.length)}\\n\\n`\n if (level === 2) return `${text}\\n${'-'.repeat(text.length)}\\n\\n`\n return `${text}\\n\\n`\n }\n\n case 'text':\n return `${renderChildren(node.children)}\\n\\n`\n\n case 'link':\n return `${renderChildren(node.children)} (${p.href})`\n\n case 'image': {\n const alt = (p.alt as string) ?? 'Image'\n const caption = p.caption ? ` — ${p.caption}` : ''\n return `[${alt}${caption}]\\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 // Calculate column widths\n const widths = columns.map((col, i) => {\n const headerLen = col.header.length\n const maxDataLen = rows.reduce(\n (max, row) => Math.max(max, String(row[i] ?? '').length),\n 0,\n )\n return Math.max(headerLen, maxDataLen, 3)\n })\n\n // Header\n const header = columns\n .map((col, i) => pad(col.header, widths[i] ?? 3, col.align))\n .join(' | ')\n const separator = widths.map((w) => '-'.repeat(w ?? 3)).join('-+-')\n\n // Rows\n const body = rows\n .map((row) =>\n columns\n .map((col, i) =>\n pad(String(row[i] ?? ''), widths[i] ?? 3, col.align),\n )\n .join(' | '),\n )\n .join('\\n')\n\n let result = `${header}\\n${separator}\\n${body}\\n\\n`\n if (p.caption) result = `${p.caption}\\n\\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} ${renderChildren(item.children)}`\n })\n .join('\\n')}\\n\\n`\n }\n\n case 'list-item':\n return renderChildren(node.children)\n\n case 'code':\n return `${renderChildren(node.children)}\\n\\n`\n\n case 'divider':\n return `${'─'.repeat(40)}\\n\\n`\n\n case 'page-break':\n return `\\n${'═'.repeat(40)}\\n\\n`\n\n case 'spacer':\n return '\\n'\n\n case 'button':\n return `[${renderChildren(node.children)}] → ${p.href}\\n\\n`\n\n case 'quote':\n return ` \"${renderChildren(node.children)}\"\\n\\n`\n\n default:\n return renderChildren(node.children)\n }\n}\n\nexport const textRenderer: 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 +1 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/builder.ts","../../../src/nodes.ts","../../../src/download.ts","../../../src/render.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/builder.ts","../../../src/nodes.ts","../../../src/download.ts","../../../src/render.ts"],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { n as sanitizeHref } from "./sanitize-O_3j1mNJ.js";
2
+
1
3
  //#region src/renderers/whatsapp.ts
2
4
  /**
3
5
  * WhatsApp renderer — outputs formatted text using WhatsApp's markup.
@@ -26,7 +28,7 @@ function renderNode(node) {
26
28
  return `${text}\n\n`;
27
29
  }
28
30
  case "link": {
29
- const href = p.href;
31
+ const href = sanitizeHref(p.href);
30
32
  return `${getTextContent(node.children)}: ${href}\n\n`;
31
33
  }
32
34
  case "image": return "";
@@ -48,7 +50,7 @@ function renderNode(node) {
48
50
  case "page-break": return "───────────\n\n";
49
51
  case "spacer": return "\n";
50
52
  case "button": {
51
- const href = p.href;
53
+ const href = sanitizeHref(p.href);
52
54
  return `*${getTextContent(node.children)}*: ${href}\n\n`;
53
55
  }
54
56
  case "quote": return `> ${getTextContent(node.children)}\n\n`;
@@ -61,4 +63,4 @@ const whatsappRenderer = { async render(node, _options) {
61
63
 
62
64
  //#endregion
63
65
  export { whatsappRenderer };
64
- //# sourceMappingURL=whatsapp-DJ2D1jGG.js.map
66
+ //# sourceMappingURL=whatsapp-CjSGoOKx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whatsapp-CjSGoOKx.js","names":[],"sources":["../src/renderers/whatsapp.ts"],"sourcesContent":["import { sanitizeHref } from '../sanitize'\nimport 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 = sanitizeHref(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 = sanitizeHref(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":";;;;;;;AAcA,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,aAAa,EAAE,KAAe;AAE3C,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,aAAa,EAAE,KAAe;AAE3C,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"}
@@ -196,4 +196,4 @@ const xlsxRenderer = { async render(node, _options) {
196
196
 
197
197
  //#endregion
198
198
  export { xlsxRenderer };
199
- //# sourceMappingURL=xlsx-D47x-gZ5.js.map
199
+ //# sourceMappingURL=xlsx-Bb5TWyXQ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"xlsx-D47x-gZ5.js","names":[],"sources":["../src/renderers/xlsx.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * XLSX renderer — lazy-loads ExcelJS on first use.\n * Extracts tables from the document and renders each as a worksheet.\n * Non-table content (headings, text) becomes header rows.\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 ExtractedSheet {\n name: string\n headings: string[]\n tables: DocNode[]\n}\n\n/** Walk the tree and group content into sheets (one per page, or one global). */\nfunction extractSheets(node: DocNode): ExtractedSheet[] {\n const sheets: ExtractedSheet[] = []\n let currentSheet: ExtractedSheet = {\n name: 'Sheet 1',\n headings: [],\n tables: [],\n }\n\n function walk(n: DocNode): void {\n switch (n.type) {\n case 'document':\n walkChildren(n)\n break\n\n case 'page':\n pushCurrentSheet()\n currentSheet = {\n name: `Sheet ${sheets.length + 1}`,\n headings: [],\n tables: [],\n }\n walkChildren(n)\n break\n\n case 'heading':\n addHeading(n)\n break\n\n case 'table':\n currentSheet.tables.push(n)\n break\n\n default:\n walkChildren(n)\n }\n }\n\n function walkChildren(n: DocNode): void {\n for (const child of n.children) {\n if (typeof child !== 'string') walk(child)\n }\n }\n\n function pushCurrentSheet(): void {\n if (currentSheet.tables.length > 0 || currentSheet.headings.length > 0) {\n sheets.push(currentSheet)\n }\n }\n\n function addHeading(n: DocNode): void {\n const text = getTextContent(n.children)\n currentSheet.headings.push(text)\n if (currentSheet.headings.length === 1) {\n currentSheet.name = text.slice(0, 31) // Excel sheet name max 31 chars\n }\n }\n\n walk(node)\n pushCurrentSheet()\n\n return sheets\n}\n\n/** Parse a cell value, handling currencies, percentages, and plain numbers. */\nfunction parseCellValue(value: string | number | undefined): string | number {\n if (value == null) return ''\n if (typeof value === 'number') return value\n\n const trimmed = value.trim()\n\n // Percentage: \"45%\" or \"12.5%\"\n if (/^-?\\d+(\\.\\d+)?%$/.test(trimmed)) {\n return Number.parseFloat(trimmed) / 100\n }\n\n // Currency: \"$1,234.56\", \"$1234\", \"-$500\"\n const currencyMatch = trimmed.match(/^-?\\$[\\d,]+(\\.\\d+)?$/)\n if (currencyMatch) {\n return Number.parseFloat(trimmed.replace(/[$,]/g, ''))\n }\n\n // Plain number: \"1,234.56\", \"1234\", \"-500.5\"\n const plainNum = Number(trimmed.replace(/,/g, ''))\n if (!Number.isNaN(plainNum) && /^-?[\\d,]+(\\.\\d+)?$/.test(trimmed)) {\n return plainNum\n }\n\n return value\n}\n\n/** Get ExcelJS number format string for a value. */\nfunction getCellFormat(\n originalValue: string | number | undefined,\n): string | undefined {\n if (typeof originalValue !== 'string') return undefined\n const trimmed = originalValue.trim()\n\n if (/^-?\\d+(\\.\\d+)?%$/.test(trimmed)) return '0.00%'\n if (/^-?\\$/.test(trimmed)) return '$#,##0.00'\n return undefined\n}\n\n/** Map alignment string to ExcelJS horizontal alignment. */\nfunction mapAlignment(align?: string): 'left' | 'center' | 'right' | undefined {\n if (align === 'left' || align === 'center' || align === 'right') return align\n return undefined\n}\n\n/** Thin border style for ExcelJS. */\nfunction thinBorder(): { style: 'thin'; color: { argb: string } } {\n return { style: 'thin', color: { argb: 'FFDDDDDD' } }\n}\n\n/** Apply header styling to a cell. */\nfunction styleHeaderCell(\n cell: {\n font: unknown\n fill: unknown\n alignment: unknown\n border: unknown\n value: unknown\n },\n col: TableColumn,\n hs: { background?: string; color?: string } | undefined,\n bordered: boolean,\n): void {\n cell.value = col.header\n cell.font = {\n bold: true,\n color: { argb: hs?.color?.replace('#', 'FF') ?? 'FF000000' },\n }\n if (hs?.background) {\n cell.fill = {\n type: 'pattern',\n pattern: 'solid',\n fgColor: { argb: hs.background.replace('#', 'FF') },\n }\n }\n cell.alignment = { horizontal: mapAlignment(col.align) ?? 'left' }\n if (bordered) {\n cell.border = {\n top: thinBorder(),\n bottom: thinBorder(),\n left: thinBorder(),\n right: thinBorder(),\n }\n }\n}\n\n/** Apply data cell value and styling. */\nfunction styleDataCell(\n cell: {\n value: unknown\n numFmt: unknown\n alignment: unknown\n fill: unknown\n border: unknown\n },\n rawValue: string | number | undefined,\n col: TableColumn,\n striped: boolean,\n isOddRow: boolean,\n bordered: boolean,\n): void {\n cell.value = parseCellValue(rawValue)\n const fmt = getCellFormat(rawValue)\n if (fmt) cell.numFmt = fmt\n cell.alignment = { horizontal: mapAlignment(col.align) ?? 'left' }\n if (striped && isOddRow) {\n cell.fill = {\n type: 'pattern',\n pattern: 'solid',\n fgColor: { argb: 'FFF9F9F9' },\n }\n }\n if (bordered) {\n cell.border = {\n top: thinBorder(),\n bottom: thinBorder(),\n left: thinBorder(),\n right: thinBorder(),\n }\n }\n}\n\n/** Render a single table node into the worksheet starting at the given row. Returns the next row number. */\nfunction renderTable(\n ws: {\n getRow: (n: number) => { getCell: (n: number) => Record<string, unknown> }\n columns: unknown[]\n },\n tableNode: DocNode,\n startRow: number,\n): number {\n let rowNum = startRow\n const columns = (\n (tableNode.props.columns ?? []) as (string | TableColumn)[]\n ).map(resolveColumn)\n const rows = (tableNode.props.rows ?? []) as (string | number)[][]\n const hs = tableNode.props.headerStyle as\n | { background?: string; color?: string }\n | undefined\n const bordered = (tableNode.props.bordered as boolean) ?? false\n\n // Caption\n if (tableNode.props.caption) {\n const captionRow = ws.getRow(rowNum)\n const captionCell = captionRow.getCell(1)\n captionCell.value = tableNode.props.caption as string\n captionCell.font = { italic: true, size: 10 }\n rowNum++\n }\n\n // Header row\n const headerRow = ws.getRow(rowNum)\n for (let i = 0; i < columns.length; i++) {\n const col = columns[i]\n if (!col) continue\n styleHeaderCell(headerRow.getCell(i + 1) as any, col, hs, bordered)\n }\n rowNum++\n\n // Data rows\n for (let r = 0; r < rows.length; r++) {\n const dataRow = ws.getRow(rowNum)\n for (let c = 0; c < columns.length; c++) {\n const col = columns[c]\n if (!col) continue\n styleDataCell(\n dataRow.getCell(c + 1) as any,\n rows[r]?.[c],\n col,\n (tableNode.props.striped as boolean) ?? false,\n r % 2 === 1,\n bordered,\n )\n }\n rowNum++\n }\n\n return rowNum + 1 // gap after table\n}\n\n/** Auto-fit column widths based on content. */\nfunction autoFitColumns(ws: {\n columns: {\n width: number\n eachCell?: (\n opts: { includeEmpty: boolean },\n cb: (cell: { value: unknown }) => void,\n ) => void\n }[]\n}): void {\n for (const col of ws.columns) {\n let maxLen = 10\n col.eachCell?.({ includeEmpty: false }, (cell) => {\n const len = String(cell.value ?? '').length\n if (len > maxLen) maxLen = len\n })\n col.width = Math.min(maxLen + 2, 50)\n }\n}\n\nexport const xlsxRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<Uint8Array> {\n const ExcelJS = await import('exceljs')\n const workbook = new ExcelJS.default.Workbook()\n\n workbook.creator = (node.props.author as string) ?? ''\n workbook.title = (node.props.title as string) ?? ''\n\n const sheets = extractSheets(node)\n\n if (sheets.length === 0) {\n workbook.addWorksheet('Sheet 1')\n }\n\n for (const sheet of sheets) {\n const ws = workbook.addWorksheet(sheet.name)\n\n let rowNum = 1\n\n // Add headings as title rows\n for (const heading of sheet.headings) {\n const row = ws.getRow(rowNum)\n row.getCell(1).value = heading\n row.getCell(1).font = { bold: true, size: 14 }\n rowNum++\n }\n\n if (sheet.headings.length > 0) rowNum++ // gap after headings\n\n // Add tables\n for (const tableNode of sheet.tables) {\n rowNum = renderTable(\n ws as unknown as Parameters<typeof renderTable>[0],\n tableNode,\n rowNum,\n )\n }\n\n // Auto-fit columns (approximate)\n autoFitColumns(ws as unknown as Parameters<typeof autoFitColumns>[0])\n }\n\n const buffer = await workbook.xlsx.writeBuffer()\n return new Uint8Array(buffer as ArrayBuffer)\n },\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"xlsx-Bb5TWyXQ.js","names":[],"sources":["../src/renderers/xlsx.ts"],"sourcesContent":["import type {\n DocChild,\n DocNode,\n DocumentRenderer,\n RenderOptions,\n TableColumn,\n} from '../types'\n\n/**\n * XLSX renderer — lazy-loads ExcelJS on first use.\n * Extracts tables from the document and renders each as a worksheet.\n * Non-table content (headings, text) becomes header rows.\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 ExtractedSheet {\n name: string\n headings: string[]\n tables: DocNode[]\n}\n\n/** Walk the tree and group content into sheets (one per page, or one global). */\nfunction extractSheets(node: DocNode): ExtractedSheet[] {\n const sheets: ExtractedSheet[] = []\n let currentSheet: ExtractedSheet = {\n name: 'Sheet 1',\n headings: [],\n tables: [],\n }\n\n function walk(n: DocNode): void {\n switch (n.type) {\n case 'document':\n walkChildren(n)\n break\n\n case 'page':\n pushCurrentSheet()\n currentSheet = {\n name: `Sheet ${sheets.length + 1}`,\n headings: [],\n tables: [],\n }\n walkChildren(n)\n break\n\n case 'heading':\n addHeading(n)\n break\n\n case 'table':\n currentSheet.tables.push(n)\n break\n\n default:\n walkChildren(n)\n }\n }\n\n function walkChildren(n: DocNode): void {\n for (const child of n.children) {\n if (typeof child !== 'string') walk(child)\n }\n }\n\n function pushCurrentSheet(): void {\n if (currentSheet.tables.length > 0 || currentSheet.headings.length > 0) {\n sheets.push(currentSheet)\n }\n }\n\n function addHeading(n: DocNode): void {\n const text = getTextContent(n.children)\n currentSheet.headings.push(text)\n if (currentSheet.headings.length === 1) {\n currentSheet.name = text.slice(0, 31) // Excel sheet name max 31 chars\n }\n }\n\n walk(node)\n pushCurrentSheet()\n\n return sheets\n}\n\n/** Parse a cell value, handling currencies, percentages, and plain numbers. */\nfunction parseCellValue(value: string | number | undefined): string | number {\n if (value == null) return ''\n if (typeof value === 'number') return value\n\n const trimmed = value.trim()\n\n // Percentage: \"45%\" or \"12.5%\"\n if (/^-?\\d+(\\.\\d+)?%$/.test(trimmed)) {\n return Number.parseFloat(trimmed) / 100\n }\n\n // Currency: \"$1,234.56\", \"$1234\", \"-$500\"\n const currencyMatch = trimmed.match(/^-?\\$[\\d,]+(\\.\\d+)?$/)\n if (currencyMatch) {\n return Number.parseFloat(trimmed.replace(/[$,]/g, ''))\n }\n\n // Plain number: \"1,234.56\", \"1234\", \"-500.5\"\n const plainNum = Number(trimmed.replace(/,/g, ''))\n if (!Number.isNaN(plainNum) && /^-?[\\d,]+(\\.\\d+)?$/.test(trimmed)) {\n return plainNum\n }\n\n return value\n}\n\n/** Get ExcelJS number format string for a value. */\nfunction getCellFormat(\n originalValue: string | number | undefined,\n): string | undefined {\n if (typeof originalValue !== 'string') return undefined\n const trimmed = originalValue.trim()\n\n if (/^-?\\d+(\\.\\d+)?%$/.test(trimmed)) return '0.00%'\n if (/^-?\\$/.test(trimmed)) return '$#,##0.00'\n return undefined\n}\n\n/** Map alignment string to ExcelJS horizontal alignment. */\nfunction mapAlignment(align?: string): 'left' | 'center' | 'right' | undefined {\n if (align === 'left' || align === 'center' || align === 'right') return align\n return undefined\n}\n\n/** Thin border style for ExcelJS. */\nfunction thinBorder(): { style: 'thin'; color: { argb: string } } {\n return { style: 'thin', color: { argb: 'FFDDDDDD' } }\n}\n\n/** Apply header styling to a cell. */\nfunction styleHeaderCell(\n cell: {\n font: unknown\n fill: unknown\n alignment: unknown\n border: unknown\n value: unknown\n },\n col: TableColumn,\n hs: { background?: string; color?: string } | undefined,\n bordered: boolean,\n): void {\n cell.value = col.header\n cell.font = {\n bold: true,\n color: { argb: hs?.color?.replace('#', 'FF') ?? 'FF000000' },\n }\n if (hs?.background) {\n cell.fill = {\n type: 'pattern',\n pattern: 'solid',\n fgColor: { argb: hs.background.replace('#', 'FF') },\n }\n }\n cell.alignment = { horizontal: mapAlignment(col.align) ?? 'left' }\n if (bordered) {\n cell.border = {\n top: thinBorder(),\n bottom: thinBorder(),\n left: thinBorder(),\n right: thinBorder(),\n }\n }\n}\n\n/** Apply data cell value and styling. */\nfunction styleDataCell(\n cell: {\n value: unknown\n numFmt: unknown\n alignment: unknown\n fill: unknown\n border: unknown\n },\n rawValue: string | number | undefined,\n col: TableColumn,\n striped: boolean,\n isOddRow: boolean,\n bordered: boolean,\n): void {\n cell.value = parseCellValue(rawValue)\n const fmt = getCellFormat(rawValue)\n if (fmt) cell.numFmt = fmt\n cell.alignment = { horizontal: mapAlignment(col.align) ?? 'left' }\n if (striped && isOddRow) {\n cell.fill = {\n type: 'pattern',\n pattern: 'solid',\n fgColor: { argb: 'FFF9F9F9' },\n }\n }\n if (bordered) {\n cell.border = {\n top: thinBorder(),\n bottom: thinBorder(),\n left: thinBorder(),\n right: thinBorder(),\n }\n }\n}\n\n/** Render a single table node into the worksheet starting at the given row. Returns the next row number. */\nfunction renderTable(\n ws: {\n getRow: (n: number) => { getCell: (n: number) => Record<string, unknown> }\n columns: unknown[]\n },\n tableNode: DocNode,\n startRow: number,\n): number {\n let rowNum = startRow\n const columns = (\n (tableNode.props.columns ?? []) as (string | TableColumn)[]\n ).map(resolveColumn)\n const rows = (tableNode.props.rows ?? []) as (string | number)[][]\n const hs = tableNode.props.headerStyle as\n | { background?: string; color?: string }\n | undefined\n const bordered = (tableNode.props.bordered as boolean) ?? false\n\n // Caption\n if (tableNode.props.caption) {\n const captionRow = ws.getRow(rowNum)\n const captionCell = captionRow.getCell(1)\n captionCell.value = tableNode.props.caption as string\n captionCell.font = { italic: true, size: 10 }\n rowNum++\n }\n\n // Header row\n const headerRow = ws.getRow(rowNum)\n for (let i = 0; i < columns.length; i++) {\n const col = columns[i]\n if (!col) continue\n styleHeaderCell(headerRow.getCell(i + 1) as any, col, hs, bordered)\n }\n rowNum++\n\n // Data rows\n for (let r = 0; r < rows.length; r++) {\n const dataRow = ws.getRow(rowNum)\n for (let c = 0; c < columns.length; c++) {\n const col = columns[c]\n if (!col) continue\n styleDataCell(\n dataRow.getCell(c + 1) as any,\n rows[r]?.[c],\n col,\n (tableNode.props.striped as boolean) ?? false,\n r % 2 === 1,\n bordered,\n )\n }\n rowNum++\n }\n\n return rowNum + 1 // gap after table\n}\n\n/** Auto-fit column widths based on content. */\nfunction autoFitColumns(ws: {\n columns: {\n width: number\n eachCell?: (\n opts: { includeEmpty: boolean },\n cb: (cell: { value: unknown }) => void,\n ) => void\n }[]\n}): void {\n for (const col of ws.columns) {\n let maxLen = 10\n col.eachCell?.({ includeEmpty: false }, (cell) => {\n const len = String(cell.value ?? '').length\n if (len > maxLen) maxLen = len\n })\n col.width = Math.min(maxLen + 2, 50)\n }\n}\n\nexport const xlsxRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<Uint8Array> {\n const ExcelJS = await import('exceljs')\n const workbook = new ExcelJS.default.Workbook()\n\n workbook.creator = (node.props.author as string) ?? ''\n workbook.title = (node.props.title as string) ?? ''\n\n const sheets = extractSheets(node)\n\n if (sheets.length === 0) {\n workbook.addWorksheet('Sheet 1')\n }\n\n for (const sheet of sheets) {\n const ws = workbook.addWorksheet(sheet.name)\n\n let rowNum = 1\n\n // Add headings as title rows\n for (const heading of sheet.headings) {\n const row = ws.getRow(rowNum)\n row.getCell(1).value = heading\n row.getCell(1).font = { bold: true, size: 14 }\n rowNum++\n }\n\n if (sheet.headings.length > 0) rowNum++ // gap after headings\n\n // Add tables\n for (const tableNode of sheet.tables) {\n rowNum = renderTable(\n ws as unknown as Parameters<typeof renderTable>[0],\n tableNode,\n rowNum,\n )\n }\n\n // Auto-fit columns (approximate)\n autoFitColumns(ws as unknown as Parameters<typeof autoFitColumns>[0])\n }\n\n const buffer = await workbook.xlsx.writeBuffer()\n return new Uint8Array(buffer as ArrayBuffer)\n },\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/document",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Universal document rendering for Pyreon — one template, every output format (HTML, PDF, DOCX, email, XLSX, Markdown, and more)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,8 +40,8 @@
40
40
  "typecheck": "tsc --noEmit"
41
41
  },
42
42
  "peerDependencies": {
43
- "@pyreon/core": ">=0.5.0 <1.0.0",
44
- "@pyreon/reactivity": ">=0.5.0 <1.0.0"
43
+ "@pyreon/core": ">=0.7.0 <0.8.0",
44
+ "@pyreon/reactivity": ">=0.7.0 <0.8.0"
45
45
  },
46
46
  "optionalDependencies": {
47
47
  "docx": "^9.6.0",
package/src/builder.ts CHANGED
@@ -136,9 +136,9 @@ export function createDocument(props: DocumentProps = {}): DocumentBuilder {
136
136
  sections.push(
137
137
  Image({
138
138
  src: dataUrl,
139
- width: p?.width,
140
- height: p?.height,
141
- caption: p?.caption,
139
+ ...(p?.width != null ? { width: p.width } : {}),
140
+ ...(p?.height != null ? { height: p.height } : {}),
141
+ ...(p?.caption != null ? { caption: p.caption } : {}),
142
142
  }),
143
143
  )
144
144
  } else {
@@ -164,9 +164,9 @@ export function createDocument(props: DocumentProps = {}): DocumentBuilder {
164
164
  sections.push(
165
165
  Image({
166
166
  src: `data:image/svg+xml,${encodeURIComponent(svg)}`,
167
- width: p?.width,
168
- height: p?.height,
169
- caption: p?.caption,
167
+ ...(p?.width != null ? { width: p.width } : {}),
168
+ ...(p?.height != null ? { height: p.height } : {}),
169
+ ...(p?.caption != null ? { caption: p.caption } : {}),
170
170
  }),
171
171
  )
172
172
  } else {
package/src/download.ts CHANGED
@@ -67,6 +67,12 @@ export async function download(
67
67
  type: MIME_TYPES[format] ?? 'application/octet-stream',
68
68
  })
69
69
 
70
+ if (typeof document === 'undefined') {
71
+ throw new Error(
72
+ '[@pyreon/document] download() requires a browser environment.',
73
+ )
74
+ }
75
+
70
76
  const url = URL.createObjectURL(blob)
71
77
  const a = document.createElement('a')
72
78
  a.href = url
package/src/nodes.ts CHANGED
@@ -37,6 +37,11 @@ function normalizeChildren(children: unknown): DocChild[] {
37
37
  if (typeof children === 'number') return [String(children)]
38
38
  if (Array.isArray(children)) return children.flatMap(normalizeChildren)
39
39
  if (isDocNode(children)) return [children]
40
+ if (typeof children === 'object') {
41
+ throw new Error(
42
+ '[@pyreon/document] Invalid child: plain objects are not valid document children. Use a document node (Text, Heading, etc.) instead.',
43
+ )
44
+ }
40
45
  return [String(children)]
41
46
  }
42
47
 
@@ -1,3 +1,4 @@
1
+ import { sanitizeHref, sanitizeImageSrc } from '../sanitize'
1
2
  import type {
2
3
  DocChild,
3
4
  DocNode,
@@ -81,7 +82,7 @@ function nodeToAdf(node: DocNode): AdfNode[] {
81
82
  }
82
83
 
83
84
  case 'link': {
84
- const href = p.href as string
85
+ const href = sanitizeHref(p.href as string)
85
86
  const text = getTextContent(node.children)
86
87
  result.push({
87
88
  type: 'paragraph',
@@ -91,7 +92,7 @@ function nodeToAdf(node: DocNode): AdfNode[] {
91
92
  }
92
93
 
93
94
  case 'image': {
94
- const src = p.src as string
95
+ const src = sanitizeImageSrc(p.src as string)
95
96
  if (src.startsWith('http')) {
96
97
  result.push({
97
98
  type: 'mediaSingle',
@@ -191,7 +192,7 @@ function nodeToAdf(node: DocNode): AdfNode[] {
191
192
  break
192
193
 
193
194
  case 'button': {
194
- const href = p.href as string
195
+ const href = sanitizeHref(p.href as string)
195
196
  const text = getTextContent(node.children)
196
197
  result.push({
197
198
  type: 'paragraph',
@@ -1,3 +1,4 @@
1
+ import { sanitizeHref, sanitizeImageSrc } from '../sanitize'
1
2
  import type {
2
3
  DocChild,
3
4
  DocNode,
@@ -36,7 +37,7 @@ function extractMeta(node: DocNode): { title?: string; imageUrl?: string } {
36
37
  if (level === 1) return { title: getTextContent(node.children) }
37
38
  }
38
39
  if (node.type === 'image') {
39
- const src = node.props.src as string
40
+ const src = sanitizeImageSrc(node.props.src as string)
40
41
  if (src.startsWith('http')) return { imageUrl: src }
41
42
  }
42
43
  for (const child of node.children) {
@@ -92,7 +93,7 @@ function nodeToMarkdown(
92
93
  }
93
94
 
94
95
  case 'link': {
95
- const href = p.href as string
96
+ const href = sanitizeHref(p.href as string)
96
97
  const text = getTextContent(node.children)
97
98
  content += `[${text}](${href})\n\n`
98
99
  break
@@ -157,7 +158,7 @@ function nodeToMarkdown(
157
158
  break
158
159
 
159
160
  case 'button': {
160
- const href = p.href as string
161
+ const href = sanitizeHref(p.href as string)
161
162
  const text = getTextContent(node.children)
162
163
  content += `[**${text}**](${href})\n\n`
163
164
  break
@@ -1,3 +1,4 @@
1
+ import { sanitizeHref, sanitizeXmlColor } from '../sanitize'
1
2
  import type {
2
3
  DocChild,
3
4
  DocNode,
@@ -122,7 +123,7 @@ function renderHeading(ctx: DocxCtx, n: DocNode): void {
122
123
  new docx.TextRun({
123
124
  text: getTextContent(n.children),
124
125
  bold: true,
125
- color: (p.color as string)?.replace('#', '') ?? '000000',
126
+ color: sanitizeXmlColor(p.color as string),
126
127
  }),
127
128
  ],
128
129
  alignment: alignmentMap(p.align as string) as any,
@@ -138,12 +139,14 @@ function renderTextNode(ctx: DocxCtx, n: DocNode): void {
138
139
  children: [
139
140
  new docx.TextRun({
140
141
  text: getTextContent(n.children),
141
- bold: p.bold as boolean | undefined,
142
- italics: p.italic as boolean | undefined,
143
- underline: p.underline ? {} : undefined,
144
- strike: p.strikethrough as boolean | undefined,
145
- size: p.size ? (p.size as number) * 2 : undefined,
146
- color: (p.color as string)?.replace('#', '') ?? '333333',
142
+ ...(p.bold != null ? { bold: p.bold as boolean } : {}),
143
+ ...(p.italic != null ? { italics: p.italic as boolean } : {}),
144
+ ...(p.underline ? { underline: {} } : {}),
145
+ ...(p.strikethrough != null
146
+ ? { strike: p.strikethrough as boolean }
147
+ : {}),
148
+ ...(p.size != null ? { size: (p.size as number) * 2 } : {}),
149
+ color: sanitizeXmlColor(p.color as string, '333333'),
147
150
  }),
148
151
  ],
149
152
  alignment: alignmentMap(p.align as string) as any,
@@ -159,11 +162,11 @@ function renderLink(ctx: DocxCtx, n: DocNode): void {
159
162
  new docx.Paragraph({
160
163
  children: [
161
164
  new docx.ExternalHyperlink({
162
- link: p.href as string,
165
+ link: sanitizeHref(p.href as string),
163
166
  children: [
164
167
  new docx.TextRun({
165
168
  text: getTextContent(n.children),
166
- color: (p.color as string)?.replace('#', '') ?? '4f46e5',
169
+ color: sanitizeXmlColor(p.color as string, '4f46e5'),
167
170
  underline: { type: docx.UnderlineType.SINGLE },
168
171
  }),
169
172
  ],
@@ -261,19 +264,21 @@ function renderDocxTable(ctx: DocxCtx, n: DocNode): void {
261
264
  new docx.TextRun({
262
265
  text: col.header,
263
266
  bold: true,
264
- color: hs?.color?.replace('#', '') ?? '000000',
267
+ color: sanitizeXmlColor(hs?.color),
265
268
  }),
266
269
  ],
267
270
  alignment: alignmentMap(col.align) as any,
268
271
  }),
269
272
  ],
270
- shading: hs?.background
273
+ ...(hs?.background
271
274
  ? {
272
- fill: hs.background.replace('#', ''),
273
- type: docx.ShadingType.SOLID,
275
+ shading: {
276
+ fill: sanitizeXmlColor(hs.background),
277
+ type: docx.ShadingType.SOLID,
278
+ },
274
279
  }
275
- : undefined,
276
- borders: cellBorders,
280
+ : {}),
281
+ ...(cellBorders != null ? { borders: cellBorders } : {}),
277
282
  width: getColumnWidth(col.width as string | undefined) as any,
278
283
  }),
279
284
  ),
@@ -293,11 +298,10 @@ function renderDocxTable(ctx: DocxCtx, n: DocNode): void {
293
298
  alignment: alignmentMap(col.align) as any,
294
299
  }),
295
300
  ],
296
- shading:
297
- p.striped && rowIdx % 2 === 1
298
- ? { fill: 'F9F9F9', type: docx.ShadingType.SOLID }
299
- : undefined,
300
- borders: cellBorders,
301
+ ...(p.striped && rowIdx % 2 === 1
302
+ ? { shading: { fill: 'F9F9F9', type: docx.ShadingType.SOLID } }
303
+ : {}),
304
+ ...(cellBorders != null ? { borders: cellBorders } : {}),
301
305
  width: getColumnWidth(col.width as string | undefined) as any,
302
306
  }),
303
307
  ),
@@ -345,7 +349,7 @@ function renderButtonOrQuote(ctx: DocxCtx, n: DocNode): void {
345
349
  new docx.Paragraph({
346
350
  children: [
347
351
  new docx.ExternalHyperlink({
348
- link: p.href as string,
352
+ link: sanitizeHref(p.href as string),
349
353
  children: [
350
354
  new docx.TextRun({
351
355
  text,
@@ -368,7 +372,7 @@ function renderButtonOrQuote(ctx: DocxCtx, n: DocNode): void {
368
372
  left: {
369
373
  style: docx.BorderStyle.SINGLE,
370
374
  size: 6,
371
- color: (p.borderColor as string)?.replace('#', '') ?? 'DDDDDD',
375
+ color: sanitizeXmlColor(p.borderColor as string, 'DDDDDD'),
372
376
  },
373
377
  },
374
378
  spacing: { after: 120 },
@@ -416,8 +420,9 @@ export const docxRenderer: DocumentRenderer = {
416
420
  children: [
417
421
  new docx.TextRun({ text: getTextContent(textChildren) }),
418
422
  ],
419
- numbering: ordered ? { reference: listRef, level } : undefined,
420
- bullet: ordered ? undefined : { level },
423
+ ...(ordered
424
+ ? { numbering: { reference: listRef, level } }
425
+ : { bullet: { level } }),
421
426
  }),
422
427
  )
423
428
  if (nestedList) {
@@ -494,8 +499,7 @@ export const docxRenderer: DocumentRenderer = {
494
499
  bottom: {
495
500
  style: docx.BorderStyle.SINGLE,
496
501
  size: (n.props.thickness as number | undefined) ?? 1,
497
- color:
498
- (n.props.color as string)?.replace('#', '') ?? 'DDDDDD',
502
+ color: sanitizeXmlColor(n.props.color as string, 'DDDDDD'),
499
503
  },
500
504
  },
501
505
  spacing: { before: 120, after: 120 },
@@ -595,12 +599,20 @@ export const docxRenderer: DocumentRenderer = {
595
599
  sections: [
596
600
  {
597
601
  properties: sectionProperties,
598
- headers: headerContent
599
- ? { default: new docx.Header({ children: headerContent as any }) }
600
- : undefined,
601
- footers: footerContent
602
- ? { default: new docx.Footer({ children: footerContent as any }) }
603
- : undefined,
602
+ ...(headerContent
603
+ ? {
604
+ headers: {
605
+ default: new docx.Header({ children: headerContent as any }),
606
+ },
607
+ }
608
+ : {}),
609
+ ...(footerContent
610
+ ? {
611
+ footers: {
612
+ default: new docx.Footer({ children: footerContent as any }),
613
+ },
614
+ }
615
+ : {}),
604
616
  children: children as any,
605
617
  },
606
618
  ],
@@ -1,3 +1,4 @@
1
+ import { sanitizeColor, sanitizeHref, sanitizeImageSrc } from '../sanitize'
1
2
  import type {
2
3
  DocChild,
3
4
  DocNode,
@@ -60,7 +61,9 @@ function renderNode(node: DocNode): string {
60
61
  return renderChildren(node.children)
61
62
 
62
63
  case 'section': {
63
- const bg = p.background ? `background-color:${p.background};` : ''
64
+ const bg = p.background
65
+ ? `background-color:${sanitizeColor(p.background as string)};`
66
+ : ''
64
67
  const pad = p.padding
65
68
  ? `padding:${typeof p.padding === 'number' ? `${p.padding}px` : Array.isArray(p.padding) ? (p.padding as number[]).map((v) => `${v}px`).join(' ') : '0'}`
66
69
  : 'padding:0'
@@ -100,14 +103,14 @@ function renderNode(node: DocNode): string {
100
103
  6: 14,
101
104
  }
102
105
  const size = sizes[level] ?? 24
103
- const color = (p.color as string) ?? '#000000'
106
+ const color = sanitizeColor((p.color as string) ?? '#000000')
104
107
  const align = (p.align as string) ?? 'left'
105
108
  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}>`
106
109
  }
107
110
 
108
111
  case 'text': {
109
112
  const size = (p.size as number) ?? 14
110
- const color = (p.color as string) ?? '#333333'
113
+ const color = sanitizeColor((p.color as string) ?? '#333333')
111
114
  const weight = p.bold ? 'bold' : 'normal'
112
115
  const style = p.italic ? 'italic' : 'normal'
113
116
  const decoration = p.underline
@@ -121,11 +124,11 @@ function renderNode(node: DocNode): string {
121
124
  }
122
125
 
123
126
  case 'link':
124
- return `<a href="${esc(p.href as string)}" style="color:${(p.color as string) ?? '#4f46e5'};text-decoration:underline" target="_blank">${renderChildren(node.children)}</a>`
127
+ return `<a href="${esc(sanitizeHref(p.href as string))}" style="color:${sanitizeColor((p.color as string) ?? '#4f46e5')};text-decoration:underline" target="_blank">${renderChildren(node.children)}</a>`
125
128
 
126
129
  case 'image': {
127
130
  const align = (p.align as string) ?? 'left'
128
- 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` : ''}" />`
131
+ const img = `<img src="${esc(sanitizeImageSrc(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` : ''}" />`
129
132
  if (p.caption) {
130
133
  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>`
131
134
  }
@@ -153,9 +156,9 @@ function renderNode(node: DocNode): string {
153
156
  html += '<tr>'
154
157
  for (const col of columns) {
155
158
  const bg = hs?.background
156
- ? `background-color:${hs.background};`
159
+ ? `background-color:${sanitizeColor(hs.background)};`
157
160
  : 'background-color:#f5f5f5;'
158
- const color = hs?.color ? `color:${hs.color};` : ''
161
+ const color = hs?.color ? `color:${sanitizeColor(hs.color)};` : ''
159
162
  const align = col.align ? `text-align:${col.align};` : ''
160
163
  const width = col.width
161
164
  ? `width:${typeof col.width === 'number' ? `${col.width}px` : col.width};`
@@ -190,7 +193,7 @@ function renderNode(node: DocNode): string {
190
193
  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>`
191
194
 
192
195
  case 'divider': {
193
- const color = (p.color as string) ?? '#dddddd'
196
+ const color = sanitizeColor((p.color as string) ?? '#dddddd')
194
197
  const thickness = (p.thickness as number) ?? 1
195
198
  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>`
196
199
  }
@@ -202,10 +205,10 @@ function renderNode(node: DocNode): string {
202
205
  return `<div style="height:${p.height}px;line-height:${p.height}px;font-size:0">&nbsp;</div>`
203
206
 
204
207
  case 'button': {
205
- const bg = (p.background as string) ?? '#4f46e5'
206
- const color = (p.color as string) ?? '#ffffff'
208
+ const bg = sanitizeColor((p.background as string) ?? '#4f46e5')
209
+ const color = sanitizeColor((p.color as string) ?? '#ffffff')
207
210
  const radius = (p.borderRadius as number) ?? 4
208
- const href = esc(p.href as string)
211
+ const href = esc(sanitizeHref(p.href as string))
209
212
  const text = renderChildren(node.children)
210
213
  const align = (p.align as string) ?? 'left'
211
214
 
@@ -214,7 +217,7 @@ function renderNode(node: DocNode): string {
214
217
  }
215
218
 
216
219
  case 'quote': {
217
- const borderColor = (p.borderColor as string) ?? '#dddddd'
220
+ const borderColor = sanitizeColor((p.borderColor as string) ?? '#dddddd')
218
221
  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>`
219
222
  }
220
223
 
@@ -1,3 +1,4 @@
1
+ import { sanitizeHref, sanitizeImageSrc } from '../sanitize'
1
2
  import type {
2
3
  DocChild,
3
4
  DocNode,
@@ -68,7 +69,7 @@ function nodeToWidgets(node: DocNode): CardWidget[] {
68
69
  }
69
70
 
70
71
  case 'link': {
71
- const href = p.href as string
72
+ const href = sanitizeHref(p.href as string)
72
73
  const text = getTextContent(node.children)
73
74
  widgets.push({
74
75
  textParagraph: { text: `<a href="${href}">${text}</a>` },
@@ -77,7 +78,7 @@ function nodeToWidgets(node: DocNode): CardWidget[] {
77
78
  }
78
79
 
79
80
  case 'image': {
80
- const src = p.src as string
81
+ const src = sanitizeImageSrc(p.src as string)
81
82
  if (src.startsWith('http')) {
82
83
  widgets.push({
83
84
  image: {
@@ -142,7 +143,7 @@ function nodeToWidgets(node: DocNode): CardWidget[] {
142
143
  break
143
144
 
144
145
  case 'button': {
145
- const href = p.href as string
146
+ const href = sanitizeHref(p.href as string)
146
147
  const text = getTextContent(node.children)
147
148
  widgets.push({
148
149
  buttonList: {