@pyreon/document 0.9.0 → 0.11.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.
- package/lib/analysis/index.js.html +1 -1
- package/lib/confluence-Bd3ua1Ut.js.map +1 -1
- package/lib/csv-COrS4qdy.js.map +1 -1
- package/lib/discord-BLUnkEh9.js.map +1 -1
- package/lib/{dist-BsqdI2nY.js → dist-CYL41kqQ.js} +2 -2
- package/lib/dist-CYL41kqQ.js.map +1 -0
- package/lib/{docx-BEBOihjl.js → docx-uNAel545.js} +7 -2
- package/lib/docx-uNAel545.js.map +1 -0
- package/lib/email-D0bbfWq4.js.map +1 -1
- package/lib/{exceljs-BoIDUUaw.js → exceljs-BYETsesT.js} +314 -314
- package/lib/exceljs-BYETsesT.js.map +1 -0
- package/lib/google-chat-CkKCBUWC.js.map +1 -1
- package/lib/html-B5biprN2.js.map +1 -1
- package/lib/index.js +17 -8
- package/lib/index.js.map +1 -1
- package/lib/markdown-CdtlFGC0.js.map +1 -1
- package/lib/notion-iG2C5bEY.js.map +1 -1
- package/lib/{pdf-DIUQUEdj.js → pdf-IuBgTb3T.js} +9 -3
- package/lib/pdf-IuBgTb3T.js.map +1 -0
- package/lib/{pdfmake-DnmLxK4Q.js → pdfmake-CKMX5URW.js} +2 -4
- package/lib/pdfmake-CKMX5URW.js.map +1 -0
- package/lib/{pptx-Dd33oL3_.js → pptx-DXiMiYFM.js} +7 -2
- package/lib/pptx-DXiMiYFM.js.map +1 -0
- package/lib/{pptxgen.es-COcgXsyx.js → pptxgen.es-FsqHs8mD.js} +3 -6
- package/lib/pptxgen.es-FsqHs8mD.js.map +1 -0
- package/lib/sanitize-O_3j1mNJ.js.map +1 -1
- package/lib/slack-BI3EQwYm.js.map +1 -1
- package/lib/svg-BKxumy-p.js.map +1 -1
- package/lib/teams-Cwz9lce0.js.map +1 -1
- package/lib/telegram-gYFqyMXb.js.map +1 -1
- package/lib/text-l1XNXBOC.js.map +1 -1
- package/lib/types/index.d.ts +43 -39
- package/lib/types/index.d.ts.map +1 -1
- package/lib/{vfs_fonts-Df1kkZ4Y.js → vfs_fonts-Cap07Jg3.js} +2 -2
- package/lib/vfs_fonts-Cap07Jg3.js.map +1 -0
- package/lib/whatsapp-CjSGoOKx.js.map +1 -1
- package/lib/{xlsx-Bb5TWyXQ.js → xlsx-Cvu4LBNy.js} +8 -2
- package/lib/xlsx-Cvu4LBNy.js.map +1 -0
- package/package.json +19 -7
- package/src/builder.ts +53 -44
- package/src/download.ts +32 -36
- package/src/env.d.ts +3 -17
- package/src/index.ts +6 -8
- package/src/nodes.ts +45 -45
- package/src/render.ts +45 -118
- package/src/renderers/confluence.ts +64 -80
- package/src/renderers/csv.ts +11 -18
- package/src/renderers/discord.ts +38 -50
- package/src/renderers/docx.ts +78 -120
- package/src/renderers/email.ts +73 -92
- package/src/renderers/google-chat.ts +35 -47
- package/src/renderers/html.ts +78 -101
- package/src/renderers/markdown.ts +43 -53
- package/src/renderers/notion.ts +63 -85
- package/src/renderers/pdf.ts +92 -115
- package/src/renderers/pptx.ts +60 -66
- package/src/renderers/slack.ts +49 -61
- package/src/renderers/svg.ts +49 -63
- package/src/renderers/teams.ts +68 -80
- package/src/renderers/telegram.ts +40 -54
- package/src/renderers/text.ts +44 -66
- package/src/renderers/whatsapp.ts +34 -48
- package/src/renderers/xlsx.ts +47 -61
- package/src/sanitize.ts +21 -25
- package/src/tests/document.test.ts +1337 -1385
- package/src/tests/stress.test.ts +350 -0
- package/src/types.ts +66 -65
- package/lib/dist-BsqdI2nY.js.map +0 -1
- package/lib/docx-BEBOihjl.js.map +0 -1
- package/lib/exceljs-BoIDUUaw.js.map +0 -1
- package/lib/pdf-DIUQUEdj.js.map +0 -1
- package/lib/pdfmake-DnmLxK4Q.js.map +0 -1
- package/lib/pptx-Dd33oL3_.js.map +0 -1
- package/lib/pptxgen.es-COcgXsyx.js.map +0 -1
- package/lib/vfs_fonts-Df1kkZ4Y.js.map +0 -1
- package/lib/xlsx-Bb5TWyXQ.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize-O_3j1mNJ.js","names":[],"sources":["../src/sanitize.ts"],"sourcesContent":["/**\n * Shared sanitization utilities for document renderers.\n * Prevents XSS via CSS injection, XML injection, and javascript: protocol attacks.\n */\n\n/**\n * Sanitize a CSS value — strips characters that could break out of a CSS property.\n * Blocks: semicolons, braces, angle brackets, quotes, backslashes, expressions.\n */\nexport function sanitizeCss(value: string | undefined): string {\n if (value == null) return
|
|
1
|
+
{"version":3,"file":"sanitize-O_3j1mNJ.js","names":[],"sources":["../src/sanitize.ts"],"sourcesContent":["/**\n * Shared sanitization utilities for document renderers.\n * Prevents XSS via CSS injection, XML injection, and javascript: protocol attacks.\n */\n\n/**\n * Sanitize a CSS value — strips characters that could break out of a CSS property.\n * Blocks: semicolons, braces, angle brackets, quotes, backslashes, expressions.\n */\nexport function sanitizeCss(value: string | undefined): string {\n if (value == null) return \"\"\n // Remove anything that could break out of a CSS value\n return value\n .replace(/[;{}()<>\\\\'\"]/g, \"\")\n .replace(/expression\\s*\\(/gi, \"\")\n .replace(/url\\s*\\(/gi, \"\")\n .replace(/javascript\\s*:/gi, \"\")\n}\n\n/**\n * Sanitize a color value — only allows hex colors, named colors, rgb/rgba, hsl/hsla.\n * Returns the value if valid, empty string if not.\n */\nexport function sanitizeColor(value: string | undefined): string {\n if (value == null) return \"\"\n const trimmed = value.trim()\n // Hex: #fff, #ffffff, #ffffffff\n if (/^#[0-9a-fA-F]{3,8}$/.test(trimmed)) return trimmed\n // Named colors (common subset)\n if (/^[a-zA-Z]{1,20}$/.test(trimmed)) return trimmed\n // rgb/rgba/hsl/hsla\n if (/^(rgb|hsl)a?\\(\\s*[\\d.,\\s%]+\\)$/.test(trimmed)) return trimmed\n // transparent, inherit, currentColor\n if (/^(transparent|inherit|currentColor|initial|unset)$/i.test(trimmed)) return trimmed\n return \"\"\n}\n\n/**\n * Sanitize a color for XML attributes (DOCX/PPTX) — only hex without #.\n * Returns 6-char hex string or default.\n */\nexport function sanitizeXmlColor(value: string | undefined, fallback = \"000000\"): string {\n if (value == null) return fallback\n const hex = value.replace(\"#\", \"\")\n if (/^[0-9a-fA-F]{3,8}$/.test(hex)) return hex\n return fallback\n}\n\n/**\n * Sanitize a URL — blocks javascript:, data: (except images), and vbscript: protocols.\n * Returns the URL if safe, empty string if not.\n */\nexport function sanitizeHref(url: string | undefined): string {\n if (url == null) return \"\"\n const trimmed = url.trim()\n // Block dangerous protocols\n const lower = trimmed.toLowerCase().replace(/\\s/g, \"\")\n if (lower.startsWith(\"javascript:\")) return \"\"\n if (lower.startsWith(\"vbscript:\")) return \"\"\n if (lower.startsWith(\"data:\") && !lower.startsWith(\"data:image/\")) return \"\"\n return trimmed\n}\n\n/**\n * Sanitize an image src — allows http(s), data:image, and relative paths.\n * Blocks javascript:, vbscript:, and non-image data: URIs.\n */\nexport function sanitizeImageSrc(src: string | undefined): string {\n if (src == null) return \"\"\n const trimmed = src.trim()\n const lower = trimmed.toLowerCase().replace(/\\s/g, \"\")\n if (lower.startsWith(\"javascript:\")) return \"\"\n if (lower.startsWith(\"vbscript:\")) return \"\"\n if (lower.startsWith(\"data:\") && !lower.startsWith(\"data:image/\")) return \"\"\n return trimmed\n}\n\n/**\n * Sanitize a style attribute value — validates it's safe CSS.\n */\nexport function sanitizeStyle(value: string | undefined): string {\n if (value == null) return \"\"\n return sanitizeCss(value)\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,YAAY,OAAmC;AAC7D,KAAI,SAAS,KAAM,QAAO;AAE1B,QAAO,MACJ,QAAQ,kBAAkB,GAAG,CAC7B,QAAQ,qBAAqB,GAAG,CAChC,QAAQ,cAAc,GAAG,CACzB,QAAQ,oBAAoB,GAAG;;;;;;AAOpC,SAAgB,cAAc,OAAmC;AAC/D,KAAI,SAAS,KAAM,QAAO;CAC1B,MAAM,UAAU,MAAM,MAAM;AAE5B,KAAI,sBAAsB,KAAK,QAAQ,CAAE,QAAO;AAEhD,KAAI,mBAAmB,KAAK,QAAQ,CAAE,QAAO;AAE7C,KAAI,iCAAiC,KAAK,QAAQ,CAAE,QAAO;AAE3D,KAAI,sDAAsD,KAAK,QAAQ,CAAE,QAAO;AAChF,QAAO;;;;;;AAOT,SAAgB,iBAAiB,OAA2B,WAAW,UAAkB;AACvF,KAAI,SAAS,KAAM,QAAO;CAC1B,MAAM,MAAM,MAAM,QAAQ,KAAK,GAAG;AAClC,KAAI,qBAAqB,KAAK,IAAI,CAAE,QAAO;AAC3C,QAAO;;;;;;AAOT,SAAgB,aAAa,KAAiC;AAC5D,KAAI,OAAO,KAAM,QAAO;CACxB,MAAM,UAAU,IAAI,MAAM;CAE1B,MAAM,QAAQ,QAAQ,aAAa,CAAC,QAAQ,OAAO,GAAG;AACtD,KAAI,MAAM,WAAW,cAAc,CAAE,QAAO;AAC5C,KAAI,MAAM,WAAW,YAAY,CAAE,QAAO;AAC1C,KAAI,MAAM,WAAW,QAAQ,IAAI,CAAC,MAAM,WAAW,cAAc,CAAE,QAAO;AAC1E,QAAO;;;;;;AAOT,SAAgB,iBAAiB,KAAiC;AAChE,KAAI,OAAO,KAAM,QAAO;CACxB,MAAM,UAAU,IAAI,MAAM;CAC1B,MAAM,QAAQ,QAAQ,aAAa,CAAC,QAAQ,OAAO,GAAG;AACtD,KAAI,MAAM,WAAW,cAAc,CAAE,QAAO;AAC5C,KAAI,MAAM,WAAW,YAAY,CAAE,QAAO;AAC1C,KAAI,MAAM,WAAW,QAAQ,IAAI,CAAC,MAAM,WAAW,cAAc,CAAE,QAAO;AAC1E,QAAO;;;;;AAMT,SAAgB,cAAc,OAAmC;AAC/D,KAAI,SAAS,KAAM,QAAO;AAC1B,QAAO,YAAY,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-BI3EQwYm.js","names":[],"sources":["../src/renderers/slack.ts"],"sourcesContent":["import { sanitizeHref, sanitizeImageSrc } from
|
|
1
|
+
{"version":3,"file":"slack-BI3EQwYm.js","names":[],"sources":["../src/renderers/slack.ts"],"sourcesContent":["import { sanitizeHref, sanitizeImageSrc } from \"../sanitize\"\nimport type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } 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) => (typeof c === \"string\" ? c : getTextContent((c as DocNode).children)))\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 = sanitizeHref(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 = sanitizeImageSrc(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(resolveColumn)\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.map((row) => row.map((cell) => String(cell ?? \"\")).join(\" | \")).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 = sanitizeHref(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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"}
|
package/lib/svg-BKxumy-p.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svg-BKxumy-p.js","names":[],"sources":["../src/renderers/svg.ts"],"sourcesContent":["import { sanitizeColor, sanitizeHref, sanitizeImageSrc } from '../sanitize'\nimport 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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\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 = sanitizeColor((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 = sanitizeColor((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 = sanitizeHref(p.href as string)\n const text = escapeXml(getTextContent(node.children))\n const color = sanitizeColor((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 = sanitizeImageSrc(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 = sanitizeColor(hs?.background ?? '#f5f5f5')\n const headerColor = sanitizeColor(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 = sanitizeColor((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 = sanitizeColor((p.background as string) ?? '#4f46e5')\n const color = sanitizeColor((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 = sanitizeColor((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
|
+
{"version":3,"file":"svg-BKxumy-p.js","names":[],"sources":["../src/renderers/svg.ts"],"sourcesContent":["import { sanitizeColor, sanitizeHref, sanitizeImageSrc } from \"../sanitize\"\nimport type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } 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, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) => (typeof c === \"string\" ? c : getTextContent((c as DocNode).children)))\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 = sanitizeColor((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 = sanitizeColor((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 = sanitizeHref(p.href as string)\n const text = escapeXml(getTextContent(node.children))\n const color = sanitizeColor((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 = sanitizeImageSrc(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(resolveColumn)\n const rows = (p.rows ?? []) as (string | number)[][]\n const hs = p.headerStyle as { background?: string; color?: string } | undefined\n const striped = p.striped as boolean | undefined\n\n const colWidth = contentWidth / columns.length\n const rowHeight = 28\n const headerBg = sanitizeColor(hs?.background ?? \"#f5f5f5\")\n const headerColor = sanitizeColor(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((c): c is DocNode => typeof c !== \"string\")\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 = sanitizeColor((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 = sanitizeColor((p.background as string) ?? \"#4f46e5\")\n const color = sanitizeColor((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 = sanitizeColor((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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teams-Cwz9lce0.js","names":[],"sources":["../src/renderers/teams.ts"],"sourcesContent":["import { sanitizeHref, sanitizeImageSrc } from
|
|
1
|
+
{"version":3,"file":"teams-Cwz9lce0.js","names":[],"sources":["../src/renderers/teams.ts"],"sourcesContent":["import { sanitizeHref, sanitizeImageSrc } from \"../sanitize\"\nimport type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } 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) => (typeof c === \"string\" ? c : getTextContent((c as DocNode).children)))\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 ? { size: (p.size as number) >= 18 ? \"large\" : \"default\" } : {}),\n })\n break\n }\n\n case \"link\": {\n const href = sanitizeHref(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 = sanitizeImageSrc(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(resolveColumn)\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: sanitizeHref(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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telegram-gYFqyMXb.js","names":[],"sources":["../src/renderers/telegram.ts"],"sourcesContent":["import { sanitizeHref } from
|
|
1
|
+
{"version":3,"file":"telegram-gYFqyMXb.js","names":[],"sources":["../src/renderers/telegram.ts"],"sourcesContent":["import { sanitizeHref } from \"../sanitize\"\nimport type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } 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, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) => (typeof c === \"string\" ? c : getTextContent((c as DocNode).children)))\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.map((c) => (typeof c === \"string\" ? esc(c) : renderNode(c))).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 = sanitizeHref(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(resolveColumn)\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.map((row) => row.map((c) => String(c ?? \"\")).join(\" | \")).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 = sanitizeHref(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":"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"}
|
package/lib/text-l1XNXBOC.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-l1XNXBOC.js","names":[],"sources":["../src/renderers/text.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"text-l1XNXBOC.js","names":[],"sources":["../src/renderers/text.ts"],"sourcesContent":["import type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } 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(str: string, width: number, align: \"left\" | \"center\" | \"right\" = \"left\"): 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) 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(resolveColumn)\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((max, row) => Math.max(max, String(row[i] ?? \"\").length), 0)\n return Math.max(headerLen, maxDataLen, 3)\n })\n\n // Header\n const header = columns.map((col, i) => pad(col.header, widths[i] ?? 3, col.align)).join(\" | \")\n const separator = widths.map((w) => \"-\".repeat(w ?? 3)).join(\"-+-\")\n\n // Rows\n const body = rows\n .map((row) =>\n columns.map((col, i) => pad(String(row[i] ?? \"\"), widths[i] ?? 3, col.align)).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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"}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
|
-
type NodeType =
|
|
2
|
+
type NodeType = "document" | "page" | "section" | "row" | "column" | "heading" | "text" | "link" | "image" | "table" | "list" | "list-item" | "page-break" | "code" | "divider" | "spacer" | "button" | "quote";
|
|
3
3
|
/** A format-agnostic document node. */
|
|
4
4
|
interface DocNode {
|
|
5
5
|
type: NodeType;
|
|
@@ -12,12 +12,12 @@ type DocChild = DocNode | string;
|
|
|
12
12
|
interface ResolvedStyles {
|
|
13
13
|
fontSize?: number;
|
|
14
14
|
fontFamily?: string;
|
|
15
|
-
fontWeight?:
|
|
16
|
-
fontStyle?:
|
|
17
|
-
textDecoration?:
|
|
15
|
+
fontWeight?: "normal" | "bold" | number;
|
|
16
|
+
fontStyle?: "normal" | "italic";
|
|
17
|
+
textDecoration?: "none" | "underline" | "line-through";
|
|
18
18
|
color?: string;
|
|
19
19
|
backgroundColor?: string;
|
|
20
|
-
textAlign?:
|
|
20
|
+
textAlign?: "left" | "center" | "right" | "justify";
|
|
21
21
|
lineHeight?: number;
|
|
22
22
|
letterSpacing?: number;
|
|
23
23
|
padding?: number | [number, number] | [number, number, number, number];
|
|
@@ -25,7 +25,7 @@ interface ResolvedStyles {
|
|
|
25
25
|
borderRadius?: number;
|
|
26
26
|
borderWidth?: number;
|
|
27
27
|
borderColor?: string;
|
|
28
|
-
borderStyle?:
|
|
28
|
+
borderStyle?: "solid" | "dashed" | "dotted";
|
|
29
29
|
width?: number | string;
|
|
30
30
|
height?: number | string;
|
|
31
31
|
maxWidth?: number | string;
|
|
@@ -39,8 +39,8 @@ interface DocumentProps {
|
|
|
39
39
|
language?: string;
|
|
40
40
|
children?: unknown;
|
|
41
41
|
}
|
|
42
|
-
type PageSize =
|
|
43
|
-
type PageOrientation =
|
|
42
|
+
type PageSize = "A4" | "A3" | "A5" | "letter" | "legal" | "tabloid";
|
|
43
|
+
type PageOrientation = "portrait" | "landscape";
|
|
44
44
|
interface PageProps {
|
|
45
45
|
size?: PageSize;
|
|
46
46
|
orientation?: PageOrientation;
|
|
@@ -52,7 +52,7 @@ interface PageProps {
|
|
|
52
52
|
footer?: DocNode;
|
|
53
53
|
}
|
|
54
54
|
interface SectionProps {
|
|
55
|
-
direction?:
|
|
55
|
+
direction?: "column" | "row";
|
|
56
56
|
gap?: number;
|
|
57
57
|
padding?: number | [number, number] | [number, number, number, number];
|
|
58
58
|
background?: string;
|
|
@@ -62,18 +62,18 @@ interface SectionProps {
|
|
|
62
62
|
}
|
|
63
63
|
interface RowProps {
|
|
64
64
|
gap?: number;
|
|
65
|
-
align?:
|
|
65
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
66
66
|
children?: unknown;
|
|
67
67
|
}
|
|
68
68
|
interface ColumnProps {
|
|
69
69
|
width?: number | string;
|
|
70
|
-
align?:
|
|
70
|
+
align?: "start" | "center" | "end";
|
|
71
71
|
children?: unknown;
|
|
72
72
|
}
|
|
73
73
|
interface HeadingProps {
|
|
74
74
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
75
75
|
color?: string;
|
|
76
|
-
align?:
|
|
76
|
+
align?: "left" | "center" | "right";
|
|
77
77
|
children?: unknown;
|
|
78
78
|
}
|
|
79
79
|
interface TextProps {
|
|
@@ -83,7 +83,7 @@ interface TextProps {
|
|
|
83
83
|
italic?: boolean;
|
|
84
84
|
underline?: boolean;
|
|
85
85
|
strikethrough?: boolean;
|
|
86
|
-
align?:
|
|
86
|
+
align?: "left" | "center" | "right" | "justify";
|
|
87
87
|
lineHeight?: number;
|
|
88
88
|
children?: unknown;
|
|
89
89
|
}
|
|
@@ -97,13 +97,13 @@ interface ImageProps {
|
|
|
97
97
|
width?: number;
|
|
98
98
|
height?: number;
|
|
99
99
|
alt?: string;
|
|
100
|
-
align?:
|
|
100
|
+
align?: "left" | "center" | "right";
|
|
101
101
|
caption?: string;
|
|
102
102
|
}
|
|
103
103
|
interface TableColumn {
|
|
104
104
|
header: string;
|
|
105
105
|
width?: number | string;
|
|
106
|
-
align?:
|
|
106
|
+
align?: "left" | "center" | "right";
|
|
107
107
|
}
|
|
108
108
|
interface TableProps {
|
|
109
109
|
columns: (string | TableColumn)[];
|
|
@@ -143,21 +143,21 @@ interface ButtonProps {
|
|
|
143
143
|
color?: string;
|
|
144
144
|
borderRadius?: number;
|
|
145
145
|
padding?: number | [number, number];
|
|
146
|
-
align?:
|
|
146
|
+
align?: "left" | "center" | "right";
|
|
147
147
|
children?: unknown;
|
|
148
148
|
}
|
|
149
149
|
interface QuoteProps {
|
|
150
150
|
borderColor?: string;
|
|
151
151
|
children?: unknown;
|
|
152
152
|
}
|
|
153
|
-
type OutputFormat =
|
|
153
|
+
type OutputFormat = "html" | "pdf" | "docx" | "pptx" | "email" | "xlsx" | "md" | "text" | "csv" | "svg" | "slack" | "teams" | "discord" | "telegram" | "notion" | "confluence" | "whatsapp" | "google-chat";
|
|
154
154
|
interface RenderOptions {
|
|
155
155
|
/** Custom styles to apply (overrides component styles). */
|
|
156
156
|
styles?: Record<string, ResolvedStyles>;
|
|
157
157
|
/** Base URL for relative image sources. */
|
|
158
158
|
baseUrl?: string;
|
|
159
159
|
/** Text direction — 'ltr' (default) or 'rtl'. */
|
|
160
|
-
direction?:
|
|
160
|
+
direction?: "ltr" | "rtl";
|
|
161
161
|
/** Custom font configuration for PDF. */
|
|
162
162
|
fonts?: Record<string, {
|
|
163
163
|
normal?: string;
|
|
@@ -172,19 +172,23 @@ interface DocumentRenderer {
|
|
|
172
172
|
render(node: DocNode, options?: RenderOptions): Promise<RenderResult>;
|
|
173
173
|
}
|
|
174
174
|
interface DocumentBuilder {
|
|
175
|
-
heading(text: string, props?: Omit<HeadingProps,
|
|
176
|
-
text(text: string, props?: Omit<TextProps,
|
|
177
|
-
paragraph(text: string, props?: Omit<TextProps,
|
|
178
|
-
image(src: string, props?: Omit<ImageProps,
|
|
175
|
+
heading(text: string, props?: Omit<HeadingProps, "children">): DocumentBuilder;
|
|
176
|
+
text(text: string, props?: Omit<TextProps, "children">): DocumentBuilder;
|
|
177
|
+
paragraph(text: string, props?: Omit<TextProps, "children">): DocumentBuilder;
|
|
178
|
+
image(src: string, props?: Omit<ImageProps, "src">): DocumentBuilder;
|
|
179
179
|
table(props: TableProps): DocumentBuilder;
|
|
180
|
-
list(items: string[], props?: Omit<ListProps,
|
|
181
|
-
code(text: string, props?: Omit<CodeProps,
|
|
180
|
+
list(items: string[], props?: Omit<ListProps, "children">): DocumentBuilder;
|
|
181
|
+
code(text: string, props?: Omit<CodeProps, "children">): DocumentBuilder;
|
|
182
182
|
divider(props?: DividerProps): DocumentBuilder;
|
|
183
183
|
spacer(height: number): DocumentBuilder;
|
|
184
|
-
quote(text: string, props?: Omit<QuoteProps,
|
|
185
|
-
button(text: string, props: Omit<ButtonProps,
|
|
186
|
-
link(text: string, props: Omit<LinkProps,
|
|
184
|
+
quote(text: string, props?: Omit<QuoteProps, "children">): DocumentBuilder;
|
|
185
|
+
button(text: string, props: Omit<ButtonProps, "children">): DocumentBuilder;
|
|
186
|
+
link(text: string, props: Omit<LinkProps, "children">): DocumentBuilder;
|
|
187
187
|
pageBreak(): DocumentBuilder;
|
|
188
|
+
/** Add an arbitrary DocNode (or fragment returned by a helper function). */
|
|
189
|
+
add(node: DocNode | DocNode[]): DocumentBuilder;
|
|
190
|
+
/** Add a group of nodes as a logical section. */
|
|
191
|
+
section(children: DocNode[]): DocumentBuilder;
|
|
188
192
|
/** Add a chart snapshot from a @pyreon/charts instance. */
|
|
189
193
|
chart(instance: unknown, props?: {
|
|
190
194
|
width?: number;
|
|
@@ -239,6 +243,18 @@ interface DocumentBuilder {
|
|
|
239
243
|
*/
|
|
240
244
|
declare function createDocument(props?: DocumentProps): DocumentBuilder;
|
|
241
245
|
//#endregion
|
|
246
|
+
//#region src/download.d.ts
|
|
247
|
+
/**
|
|
248
|
+
* Download a document in the browser.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```tsx
|
|
252
|
+
* await download(doc, 'report.pdf')
|
|
253
|
+
* await download(doc, 'report.docx')
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
declare function download(node: DocNode, filename: string, options?: RenderOptions): Promise<void>;
|
|
257
|
+
//#endregion
|
|
242
258
|
//#region src/nodes.d.ts
|
|
243
259
|
/** Type guard — checks if a value is a DocNode. */
|
|
244
260
|
declare function isDocNode(value: unknown): value is DocNode;
|
|
@@ -473,18 +489,6 @@ declare namespace Quote {
|
|
|
473
489
|
var _documentType: "quote";
|
|
474
490
|
}
|
|
475
491
|
//#endregion
|
|
476
|
-
//#region src/download.d.ts
|
|
477
|
-
/**
|
|
478
|
-
* Download a document in the browser.
|
|
479
|
-
*
|
|
480
|
-
* @example
|
|
481
|
-
* ```tsx
|
|
482
|
-
* await download(doc, 'report.pdf')
|
|
483
|
-
* await download(doc, 'report.docx')
|
|
484
|
-
* ```
|
|
485
|
-
*/
|
|
486
|
-
declare function download(node: DocNode, filename: string, options?: RenderOptions): Promise<void>;
|
|
487
|
-
//#endregion
|
|
488
492
|
//#region src/render.d.ts
|
|
489
493
|
/**
|
|
490
494
|
* Register a custom renderer for a format.
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/builder.ts","../../../src/
|
|
1
|
+
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/builder.ts","../../../src/download.ts","../../../src/nodes.ts","../../../src/render.ts"],"mappings":";KAEY,QAAA;AAAZ;AAAA,UAqBiB,OAAA;EACf,IAAA,EAAM,QAAA;EACN,KAAA,EAAO,MAAA;EACP,QAAA,EAAU,QAAA;EAHK;EAKf,MAAA,GAAS,cAAA;AAAA;AAAA,KAGC,QAAA,GAAW,OAAA;AAAA,UAIN,cAAA;EACf,QAAA;EACA,UAAA;EACA,UAAA;EACA,SAAA;EACA,cAAA;EACA,KAAA;EACA,eAAA;EACA,SAAA;EACA,UAAA;EACA,aAAA;EACA,OAAA;EACA,MAAA;EACA,YAAA;EACA,WAAA;EACA,WAAA;EACA,WAAA;EACA,KAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA;AAAA;AAAA,UAKe,aAAA;EACf,KAAA;EACA,MAAA;EACA,OAAA;EACA,QAAA;EACA,QAAA;EACA,QAAA;AAAA;AAAA,KAGU,QAAA;AAAA,KACA,eAAA;AAAA,UAEK,SAAA;EACf,IAAA,GAAO,QAAA;EACP,WAAA,GAAc,eAAA;EACd,MAAA;EACA,QAAA;EA3BA;EA6BA,MAAA,GAAS,OAAA;EA3BT;EA6BA,MAAA,GAAS,OAAA;AAAA;AAAA,UAGM,YAAA;EACf,SAAA;EACA,GAAA;EACA,OAAA;EACA,UAAA;EACA,YAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,UAGe,QAAA;EACf,GAAA;EACA,KAAA;EACA,QAAA;AAAA;AAAA,UAGe,WAAA;EACf,KAAA;EACA,KAAA;EACA,QAAA;AAAA;AAAA,UAGe,YAAA;EACf,KAAA;EACA,KAAA;EACA,KAAA;EACA,QAAA;AAAA;AAAA,UAGe,SAAA;EACf,IAAA;EACA,KAAA;EACA,IAAA;EACA,MAAA;EACA,SAAA;EACA,aAAA;EACA,KAAA;EACA,UAAA;EACA,QAAA;AAAA;AAAA,UAGe,SAAA;EACf,IAAA;EACA,KAAA;EACA,QAAA;AAAA;AAAA,UAGe,UAAA;EACf,GAAA;EACA,KAAA;EACA,MAAA;EACA,GAAA;EACA,KAAA;EACA,OAAA;AAAA;AAAA,UAGe,WAAA;EACf,MAAA;EACA,KAAA;EACA,KAAA;AAAA;AAAA,UAGe,UAAA;EACf,OAAA,YAAmB,WAAA;EACnB,IAAA;EACA,WAAA;IACE,UAAA;IACA,KAAA;IACA,IAAA;EAAA;EAEF,OAAA;EACA,QAAA;EACA,OAAA;EA5DA;EA8DA,YAAA;AAAA;AAAA,UAGe,SAAA;EACf,OAAA;EACA,QAAA;AAAA;AAAA,UAGe,aAAA;EACf,QAAA;AAAA;AAAA,UAGe,SAAA;EACf,QAAA;EACA,QAAA;AAAA;AAAA,UAGe,YAAA;EACf,KAAA;EACA,SAAA;AAAA;AAAA,UAGe,WAAA;EACf,MAAA;AAAA;AAAA,UAGe,WAAA;EACf,IAAA;EACA,UAAA;EACA,KAAA;EACA,YAAA;EACA,OAAA;EACA,KAAA;EACA,QAAA;AAAA;AAAA,UAGe,UAAA;EACf,WAAA;EACA,QAAA;AAAA;AAAA,KAKU,YAAA;AAAA,UAoBK,aAAA;EAnGP;EAqGR,MAAA,GAAS,MAAA,SAAe,cAAA;EAlGT;EAoGf,OAAA;;EAEA,SAAA;EArGA;EAuGA,KAAA,GAAQ,MAAA;IAAiB,MAAA;IAAiB,IAAA;IAAe,OAAA;IAAkB,WAAA;EAAA;AAAA;AAAA,KAGjE,YAAA,YAAwB,UAAA;;UAGnB,gBAAA;EACf,MAAA,CAAO,IAAA,EAAM,OAAA,EAAS,OAAA,GAAU,aAAA,GAAgB,OAAA,CAAQ,YAAA;AAAA;AAAA,UAKzC,eAAA;EACf,OAAA,CAAQ,IAAA,UAAc,KAAA,GAAQ,IAAA,CAAK,YAAA,gBAA4B,eAAA;EAC/D,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,IAAA,CAAK,SAAA,gBAAyB,eAAA;EACzD,SAAA,CAAU,IAAA,UAAc,KAAA,GAAQ,IAAA,CAAK,SAAA,gBAAyB,eAAA;EAC9D,KAAA,CAAM,GAAA,UAAa,KAAA,GAAQ,IAAA,CAAK,UAAA,WAAqB,eAAA;EACrD,KAAA,CAAM,KAAA,EAAO,UAAA,GAAa,eAAA;EAC1B,IAAA,CAAK,KAAA,YAAiB,KAAA,GAAQ,IAAA,CAAK,SAAA,gBAAyB,eAAA;EAC5D,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,IAAA,CAAK,SAAA,gBAAyB,eAAA;EACzD,OAAA,CAAQ,KAAA,GAAQ,YAAA,GAAe,eAAA;EAC/B,MAAA,CAAO,MAAA,WAAiB,eAAA;EACxB,KAAA,CAAM,IAAA,UAAc,KAAA,GAAQ,IAAA,CAAK,UAAA,gBAA0B,eAAA;EAC3D,MAAA,CAAO,IAAA,UAAc,KAAA,EAAO,IAAA,CAAK,WAAA,gBAA2B,eAAA;EAC5D,IAAA,CAAK,IAAA,UAAc,KAAA,EAAO,IAAA,CAAK,SAAA,gBAAyB,eAAA;EACxD,SAAA,IAAa,eAAA;EA5GY;EA8GzB,GAAA,CAAI,IAAA,EAAM,OAAA,GAAU,OAAA,KAAY,eAAA;EA7GF;EA+G9B,OAAA,CAAQ,QAAA,EAAU,OAAA,KAAY,eAAA;EA/GX;EAiHnB,KAAA,CACE,QAAA,WACA,KAAA;IAAU,KAAA;IAAgB,MAAA;IAAiB,OAAA;EAAA,IAC1C,eAAA;EA7GH;EA+GA,IAAA,CACE,QAAA,WACA,KAAA;IAAU,KAAA;IAAgB,MAAA;IAAiB,OAAA;EAAA,IAC1C,eAAA;EA3GY;EA6Gf,KAAA,IAAS,OAAA;;EAET,MAAA,CAAO,OAAA,GAAU,aAAA,GAAgB,OAAA;EACjC,KAAA,CAAM,OAAA,GAAU,aAAA,GAAgB,OAAA,CAAQ,UAAA;EACxC,MAAA,CAAO,OAAA,GAAU,aAAA,GAAgB,OAAA,CAAQ,UAAA;EACzC,MAAA,CAAO,OAAA,GAAU,aAAA,GAAgB,OAAA,CAAQ,UAAA;EACzC,OAAA,CAAQ,OAAA,GAAU,aAAA,GAAgB,OAAA;EAClC,MAAA,CAAO,OAAA,GAAU,aAAA,GAAgB,OAAA,CAAQ,UAAA;EACzC,UAAA,CAAW,OAAA,GAAU,aAAA,GAAgB,OAAA;EACrC,MAAA,CAAO,OAAA,GAAU,aAAA,GAAgB,OAAA;EACjC,KAAA,CAAM,OAAA,GAAU,aAAA,GAAgB,OAAA;EAChC,OAAA,CAAQ,OAAA,GAAU,aAAA,GAAgB,OAAA;EAClC,KAAA,CAAM,OAAA,GAAU,aAAA,GAAgB,OAAA;EAChC,OAAA,CAAQ,OAAA,GAAU,aAAA,GAAgB,OAAA;EAClC,SAAA,CAAU,OAAA,GAAU,aAAA,GAAgB,OAAA;EACpC,UAAA,CAAW,OAAA,GAAU,aAAA,GAAgB,OAAA;EACrC,QAAA,CAAS,OAAA,GAAU,aAAA,GAAgB,OAAA;EACnC,YAAA,CAAa,OAAA,GAAU,aAAA,GAAgB,OAAA;EACvC,UAAA,CAAW,OAAA,GAAU,aAAA,GAAgB,OAAA;EACrC,YAAA,CAAa,OAAA,GAAU,aAAA,GAAgB,OAAA;EA7Gb;EA+G1B,QAAA,CAAS,QAAA,UAAkB,OAAA,GAAU,aAAA,GAAgB,OAAA;AAAA;;;AAhSvD;;;;;AAqBA;;;;;;;;;AArBA,iBCiDgB,cAAA,CAAe,KAAA,GAAO,aAAA,GAAqB,eAAA;;;ADjD3D;;;;;AAqBA;;;;AArBA,iBEuCsB,QAAA,CACpB,IAAA,EAAM,OAAA,EACN,QAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;;;AF3CH;AAAA,iBG8CgB,SAAA,CAAU,KAAA,YAAiB,KAAA,IAAS,OAAA;;;;AHzBpD;;;;;;;iBG+CgB,QAAA,CAAS,KAAA,EAAO,aAAA,GAAgB,OAAA;AAAA,kBAAhC,QAAA;EAAA,IAAQ,aAAA;AAAA;;;;;;;;;AHvCxB;;iBGuDgB,IAAA,CAAK,KAAA,EAAO,SAAA,GAAY,OAAA;AAAA,kBAAxB,IAAA;EAAA,IAAI,aAAA;AAAA;;;;;;;;;;;;iBAiBJ,OAAA,CAAQ,KAAA,EAAO,YAAA,GAAe,OAAA;AAAA,kBAA9B,OAAA;EAAA,IAAO,aAAA;AAAA;;;;;;;;;;;AH3CvB;iBG4DgB,GAAA,CAAI,KAAA,EAAO,QAAA,GAAW,OAAA;AAAA,kBAAtB,GAAA;EAAA,IAAG,aAAA;AAAA;;;;iBASH,MAAA,CAAO,KAAA,EAAO,WAAA,GAAc,OAAA;AAAA,kBAA5B,MAAA;EAAA,IAAM,aAAA;AAAA;AH5DtB;;;;;AACA;;;;AADA,iBG2EgB,OAAA,CAAQ,KAAA,EAAO,YAAA,GAAe,OAAA;AAAA,kBAA9B,OAAA;EAAA,IAAO,aAAA;AAAA;;;;;;;;;;iBAeP,IAAA,CAAK,KAAA,EAAO,SAAA,GAAY,OAAA;AAAA,kBAAxB,IAAA;EAAA,IAAI,aAAA;AAAA;;;;;;AH5EpB;;;iBG0FgB,IAAA,CAAK,KAAA,EAAO,SAAA,GAAY,OAAA;AAAA,kBAAxB,IAAA;EAAA,IAAI,aAAA;AAAA;;;;;;;AHhFpB;;;iBG+FgB,KAAA,CAAM,KAAA,EAAO,UAAA,GAAa,OAAA;AAAA,kBAA1B,KAAA;EAAA,IAAK,aAAA;AAAA;;;AHzFrB;;;;;;;;;AAMA;;iBGqGgB,KAAA,CAAM,KAAA,EAAO,UAAA,GAAa,OAAA;AAAA,kBAA1B,KAAA;EAAA,IAAK,aAAA;AAAA;;;;;AH9FrB;;;;;;;iBG8GgB,IAAA,CAAK,KAAA,EAAO,SAAA,GAAY,OAAA;AAAA,kBAAxB,IAAA;EAAA,IAAI,aAAA;AAAA;;;;iBASJ,QAAA,CAAS,KAAA,EAAO,aAAA,GAAgB,OAAA;AAAA,kBAAhC,QAAA;EAAA,IAAQ,aAAA;AAAA;;;;;;;AHrGxB;;iBGmHgB,IAAA,CAAK,KAAA,EAAO,SAAA,GAAY,OAAA;AAAA,kBAAxB,IAAA;EAAA,IAAI,aAAA;AAAA;;;;;;;AH1GpB;;iBGwHgB,OAAA,CAAQ,KAAA,GAAO,YAAA,GAAoB,OAAA;AAAA,kBAAnC,OAAA;EAAA,IAAO,aAAA;AAAA;;;;AHlHvB;;;;;;iBGgIgB,SAAA,CAAA,GAAa,OAAA;AAAA,kBAAb,SAAA;EAAA,IAAS,aAAA;AAAA;;;;;;;;AHjHzB;iBG8HgB,MAAA,CAAO,KAAA,EAAO,WAAA,GAAc,OAAA;AAAA,kBAA5B,MAAA;EAAA,IAAM,aAAA;AAAA;AHzHtB;;;;;AAIA;;;;;AAJA,iBGwIgB,MAAA,CAAO,KAAA,EAAO,WAAA,GAAc,OAAA;AAAA,kBAA5B,MAAA;EAAA,IAAM,aAAA;AAAA;;AH1HtB;;;;;AAIA;;iBGoIgB,KAAA,CAAM,KAAA,EAAO,UAAA,GAAa,OAAA;AAAA,kBAA1B,KAAA;EAAA,IAAK,aAAA;AAAA;;;AHzTrB;;;;;AAqBA;;;;;;;;;;AArBA,iBImBgB,gBAAA,CACd,MAAA,UACA,QAAA,EAAU,gBAAA,UAA0B,OAAA,CAAQ,gBAAA;;;;iBAQ9B,kBAAA,CAAmB,MAAA;;;;;AJAnC;;;;;AAIA;;;;;iBI8EsB,MAAA,CACpB,IAAA,EAAM,OAAA,EACN,MAAA,EAAQ,YAAA,WACR,OAAA,GAAU,aAAA,GACT,OAAA,CAAQ,YAAA;;iBAMK,eAAA,CAAA"}
|